Skip to content

Add SmartTrend pipe #1372

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
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6998ee6
Add SmartTrend pipe
giraffekey Feb 17, 2025
66296e1
Remove package-lock.json
giraffekey Feb 17, 2025
5ee5dfb
Fix type errors
giraffekey Feb 17, 2025
2ba1aac
Use model from settings
giraffekey Feb 17, 2025
bc7e817
Add install chrome button
giraffekey Feb 18, 2025
e3afa32
Add browser connection, storage, and status text
giraffekey Feb 19, 2025
5cfe268
Add error toasts
giraffekey Feb 19, 2025
5e1a69b
Switch from LMDB to JSON and fix type errors
giraffekey Feb 19, 2025
e0926ca
Make it open chrome if connection fails
giraffekey Feb 20, 2025
ec0607e
Show error if AI model is not configured
giraffekey Feb 20, 2025
d03410f
Add compatibility for screenpipe cloud
giraffekey Feb 20, 2025
8995a4d
Fix type error
giraffekey Feb 20, 2025
e79bc92
Add fallback for object streaming
giraffekey Feb 20, 2025
7fb1880
Uncomment other processes
giraffekey Feb 20, 2025
31a9d0d
Extract correct Twitter handle and close pages when stop button is cl…
giraffekey Feb 21, 2025
bc9b0fc
Add prompt input field
giraffekey Feb 21, 2025
62bba4b
Keep pages open to run in background
giraffekey Feb 21, 2025
1773707
Add frequency slider
giraffekey Feb 21, 2025
0d51305
Fix OpenAI text streaming
giraffekey Feb 27, 2025
959fb5b
Update settings provider
giraffekey Mar 4, 2025
42ca756
Switch to openai package
giraffekey Mar 4, 2025
3163dbf
Improve README
giraffekey Mar 6, 2025
7fb7135
Fix image url
giraffekey Mar 6, 2025
2e85931
Add ai preset
giraffekey Mar 13, 2025
aeeae84
Use presets dialog and selector
giraffekey Mar 15, 2025
5522da9
Fix type error in prompt input
giraffekey Mar 15, 2025
d61e87b
Optimize token usage
giraffekey Mar 17, 2025
3f3edf6
Stream text and show progress
giraffekey Mar 17, 2025
3d57028
Add support for ollama
giraffekey Mar 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions pipes/smarttrend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
7 changes: 7 additions & 0 deletions pipes/smarttrend/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Copyright © 2025 giraffekey <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 changes: 24 additions & 0 deletions pipes/smarttrend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# **SmartTrend: Your Twitter Engagement Assistant**

![SmartTrend Preview](https://raw.githubusercontent.com/mediar-ai/screenpipe/3163dbf999a50db79e168c965dc3cc5ace00c22d/pipes/smarttrend/preview.png)

**SmartTrend** is an AI-powered Twitter assistant that helps you discover trending topics, generate meaningful replies, and boost your engagement effortlessly. Whether you want to grow your following, maintain active discussions, or simply stay relevant, SmartTrend makes it easy by analyzing your timeline, profile, and interactions to suggest optimized replies.

---

## 🚀 **Key Features**
- **Intelligent Suggestions:** Analyzes your timeline to find tweets that align with your interests and suggests personalized replies.
- **Dynamic Frequency Control:** Adjusts how often it scans, analyzes, and generates suggestions based on your preferences.
- **Adaptive Writing Style:** Matches your tone, grammar, and formatting style, from casual to professional.
- **Engagement Filters:** Focuses on high-impact tweets with options to prioritize verified accounts, popular hashtags, or your followers.

---

## 🧠 **How It Works**
1. **Timeline Analysis:** Uses advanced scraping to extract tweets without API limits.
2. **AI-Powered Insights:** Leverages OpenAI for reply suggestions based on your profile and interactions.
3. **Local Data Storage:** Keeps everything private by storing data locally.

---

Engage smarter, not harder!
Binary file added pipes/smarttrend/bun.lockb
Binary file not shown.
21 changes: 21 additions & 0 deletions pipes/smarttrend/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
16 changes: 16 additions & 0 deletions pipes/smarttrend/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const compat = new FlatCompat({
baseDirectory: __dirname,
});

const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
];

export default eslintConfig;
5 changes: 5 additions & 0 deletions pipes/smarttrend/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
14 changes: 14 additions & 0 deletions pipes/smarttrend/next.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
transpilePackages: ["@screenpipe/js"],
webpack: (config, {}) => {
return config;
},
devIndicators: {
buildActivity: false,
appIsrStatus: false,
},
};

export default nextConfig;
83 changes: 83 additions & 0 deletions pipes/smarttrend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
{
"name": "smarttrend-pipe",
"version": "0.1.3",
"private": true,
"type": "module",
"scripts": {
"dev": "next dev --turbopack",
"build": "next build --no-lint",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@ai-sdk/openai": "^1.2.4",
"@radix-ui/react-accordion": "^1.2.3",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-progress": "^1.1.2",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slider": "^1.2.3",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-switch": "^1.1.3",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-toast": "^1.2.6",
"@radix-ui/react-tooltip": "^1.1.8",
"@screenpipe/browser": "^0.1.37",
"@screenpipe/js": "latest",
"@shadcn/ui": "^0.0.4",
"@tanstack/react-query": "^5.67.3",
"@types/js-levenshtein": "^1.1.3",
"@types/lodash": "^4.17.16",
"@types/react-syntax-highlighter": "^15.5.13",
"ai": "^4.1.60",
"class-variance-authority": "^0.7.1",
"classic-level": "^2.0.0",
"clsx": "^2.1.1",
"cmdk": "1.0.4",
"date-fns": "^4.1.0",
"dotenv": "^16.4.7",
"framer-motion": "^11.18.2",
"install": "^0.13.0",
"js-levenshtein": "^1.1.6",
"localforage": "^1.10.0",
"lodash": "^4.17.21",
"lucide-react": "^0.468.0",
"magic-ui": "^0.1.0",
"next": "15.1.0",
"node-cron": "^3.0.3",
"npm": "^10.9.2",
"ollama": "^0.5.14",
"ollama-ai-provider": "^1.2.0",
"open": "^10.1.0",
"openai": "^4.87.3",
"puppeteer-core": "^24.4.0",
"react": "^19.0.0",
"react-day-picker": "8.10.1",
"react-dom": "^19.0.0",
"react-markdown": "^9.1.0",
"react-syntax-highlighter": "^15.6.1",
"react-textarea-autosize": "^8.5.7",
"react-twitter-embed": "^4.0.4",
"remark-gfm": "^4.0.1",
"remark-math": "^6.0.0",
"sonner": "^2.0.1",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7"
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.0",
"@types/node": "^22.13.10",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"autoprefixer": "^10.4.21",
"eslint": "^9.22.0",
"eslint-config-next": "15.1.0",
"postcss": "^8.5.3",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.2",
"bun-types": "latest"
}
}
3 changes: 3 additions & 0 deletions pipes/smarttrend/pipe.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"crons": []
}
8 changes: 8 additions & 0 deletions pipes/smarttrend/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
},
};

export default config;
1 change: 1 addition & 0 deletions pipes/smarttrend/public/file.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pipes/smarttrend/public/globe.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pipes/smarttrend/public/next.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pipes/smarttrend/public/vercel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pipes/smarttrend/public/window.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 38 additions & 0 deletions pipes/smarttrend/src/app/api/errors/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { NextRequest } from "next/server";
import { eventEmitter } from "@/lib/events";

export interface Error {
title: string;
description: string;
}

export async function GET(req: NextRequest) {
const stream = new ReadableStream({
start(controller) {
const sendData = (data: Error) => {
controller.enqueue(`data: ${JSON.stringify(data)}\n\n`);
};

eventEmitter.on("catchError", sendData);

const keepAliveInterval = setInterval(() => {
controller.enqueue(new TextEncoder().encode(": keep-alive\n\n"));
}, 30_000);

req.signal.addEventListener("abort", () => {
console.log("/api/errors: Connection Closed");
eventEmitter.off("catchError", sendData);
clearInterval(keepAliveInterval);
controller.close();
});
},
});

return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
});
}
38 changes: 38 additions & 0 deletions pipes/smarttrend/src/app/api/progress/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { NextRequest } from "next/server";
import { eventEmitter } from "@/lib/events";

export interface ProgressUpdate {
process: number;
value: number;
}

export async function GET(req: NextRequest) {
const stream = new ReadableStream({
start(controller) {
const sendData = (data: ProgressUpdate) => {
controller.enqueue(`data: ${JSON.stringify(data)}\n\n`);
};

eventEmitter.on("updateProgress", sendData);

const keepAliveInterval = setInterval(() => {
controller.enqueue(new TextEncoder().encode(": keep-alive\n\n"));
}, 30_000);

req.signal.addEventListener("abort", () => {
console.log("/api/progress: Connection Closed");
eventEmitter.off("updateProgress", sendData);
clearInterval(keepAliveInterval);
controller.close();
});
},
});

return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
});
}
Loading
Loading