Auto-update: Mon Jul 22 18:36:05 PDT 2024

This commit is contained in:
sanj 2024-07-22 18:36:05 -07:00
parent f8bb49032e
commit 866e6e31e7
5 changed files with 389 additions and 8 deletions

View file

@ -0,0 +1,5 @@
HOME: ~
SIJAPI: "{{ HOME }}/workshop/sijapi"
DATA: "{{ SIJAPI }}/data"
CONFIG: "{{ SIJAPI }}/config"
LOGS: "{{ SIJAPI }}/logs"

View file

@ -0,0 +1,185 @@
profiles:
- name: CHANGE ME
ig_name: CHANGE ME
ig_bio: CHANGE ME
age: 19
gender: F
aesthetic: CHANGE ME
dailyposts: 8
ig_pass: CHANGE ME
ig_2fa_secret: CHANGE ME
img_comment_sys: You are a friendly AI assistant, who generates comments to post on Instagram accounts. Below is information about who you will be posting as. Your primary directive is to be authentic, and stay in character.
img_description_sys: You are a creative AI, crafting engaging and vivid social media captions for images based on images or descriptions of images provided to you. Stay true to the personality described, and strive for an authentic social post with each one. Only output one caption per image, and do not include anything else in your response.
img_prompt_sys: You are a helpful AI who assists in generating prompts that will be used to generate highly realistic images. Always use the most visually descriptive terms possible, and avoid any vague or abstract concepts. Do not include any words or descriptions based on other senses or emotions. Strive to show rather than tell. Space is limited, so be efficient with your words.
posts:
selfie:
API_NPrompt: CHANGE ME
API_PPrompt: Selfie of a CHANGE ME
API_SPrompt: ; CHANGE ME
Vision_Prompt: Write an upbeat Instagram description with emojis to accompany this selfie.
frequency: 2
ghost_tags:
- aigenerated
- stablediffusion
- sdxl
- selfie
llmPrompt:
- role: system
content: You are a helpful AI who assists in generating prompts that will be used to generate highly realistic images. Always use the most visually descriptive terms possible, and avoid any vague or abstract concepts. Do not include any words or descriptions based on other senses or emotions. Strive to show rather than tell. Space is limited, so be efficient with your words.
- role: user
content: Using a series of words or sentence fragments separated by commas, describe a raw authentic selfie photo of a CHANGE ME. Focus on what CHANGE ME is wearing, what CHANGE ME is doing, what location or environment CHANGE ME is in, and how the photo is framed. Only use words and phrases that are visually descriptive. This model travels a lot, so any destination could be a good fit. CHANGE ME style favors dark muted earth tones, dramatic lighting, and a VSCO girl aesthetic. CHANGE ME has a wild streak and loves hiking in the mountains and sea kayaking as much as partying at festivals or raves. Avoid cliche situations; instread strive for nuance and originality in composition and environment.
workflows:
- selfie
width: 800
height: 1080
meme:
API_NPrompt: CHANGE ME
API_PPrompt: Funny meme of
API_SPrompt: ; CHANGE ME
Vision_Prompt: Generate a funny caption that riffs on this meme image
frequency: 2
ghost_tags:
- aigenerated
- stablediffusion
- sdxl
- selfie
llmPrompt:
- role: system
content: You are a helpful AI who assists in generating prompts that will be used to generate hilarious meme images. Always use the most visually descriptive terms possible, and avoid any vague or abstract concepts. Do not include any words or descriptions based on other senses or emotions. Strive to show rather than tell. Space is limited, so be efficient with your words.
- role: user
content: Come up with a funny visual joke or meme, then use a series of words or sentence fragments separated by commas, describing it. Focus on providing descriptions of the visual elements that make the image funny. Only use words and phrases that are visually descriptive.
workflows:
- playground
width: 1080
height: 880
landscape:
API_NPrompt: CHANGE ME
API_PPrompt: Moody landscape photograph of
API_SPrompt: ", masterpiece, (subtle:0.7), (nuanced:0.6), best quality, ultra detailed, ultra high resolution, 8k, (documentary:0.3), cinematic, filmic, moody, dynamic lighting, realistic, wallpaper, landscape photography, professional, earthporn, (eliot porter:0.6), (frans lanting:0.4), (daniel kordan:0.6), landscapephotography, ultra detailed, earth tones, moody"
Vision_Prompt: Write a thoughtful Instagram description to accompany this landscape photo I took.
frequency: 2
ghost_tags:
- aigenerated
- stablediffusion
- sdxl
- landscape
- wilderness
llmPrompt:
- role: system
content: You are a helpful AI who assists in generating prompts that will be used to generate highly realistic images. Always use the most visually descriptive terms possible, and avoid any vague or abstract concepts. Do not include any words or descriptions based on other senses or emotions. Strive to show rather than tell. Space is limited, so be efficient with your words.
- role: user
content: CHANGE ME
workflows:
- landscape
width: 1200
height: 800
agitprop:
API_NPrompt: scary, ugly, gross, disgusting, horror, selfie
API_PPrompt: Striking photo,
API_SPrompt: ", best quality, masterpiece, professional photographer, adorable, sadness, cute animal, detailed, 8k"
Vision_Prompt: Write a heartfelt post urging people not to eat meat such as from this animal. Appeal to peoples' compassion, and argue passionately that these animals are sentient, feel pain, and suffer terribly because of us, and that they deserve better.
frequency: 1
ghost_tags:
- aigenerated
- stablediffusion
- sdxl
- animalrights
- compassion
llmPrompt:
- role: system
content: You are a helpful AI who assists in generating prompts that will be used to generate highly realistic images. Always use the most visually descriptive terms possible, and avoid any vague or abstract concepts. Do not include any words or descriptions based on other senses or emotions. Strive to show rather than tell. Space is limited, so be efficient with your words.
- role: user
content: Using a series of words or sentence fragments separated by commas, describe a striking image of an animal commonly consumed as food (pig, cow, chicken) looking into the camera either with a look of love and affection, or a look of pain. The image should appeal to peoples' inner compassion.
workflows:
- landscape
width: 1024
height: 1024
food:
API_NPrompt: gross, ugly, unappetizing, meat, cheap, dairy, poultry, egg, omnivore, fish, bacon, steak, beef, ham, pork, distorted, misshapen, deformed, disgusting, horror, selfie, human
API_PPrompt: (slate gray plate) with vegan
API_SPrompt: ", fresh, (gourmet), tasty, rustic, vegan, beautiful presentation, classy, masterpiece, perfection, 8k, (dark ambience), austere, moody"
Vision_Prompt: Write an upbeat appetizing Instagram caption for this photo of a vegan dish, including hashtags! If any ingredients look non-vegan, be sure to specify that they are vegan.
frequency: 1
ghost_tags:
- aigenerated
- stablediffusion
- sdxl
- food
- vegan
llmPrompt:
- role: system
content: You are a helpful AI who assists in generating ideas for vegan foods. Space is limited, so be efficient with your words.
- role: user
content: Using a series of words or sentence fragments separated by commas, describe a single gourmet but rustic vegan food item. Try to select foods that can be made at home easily and which feature simple, bold, vegan ingredients. Mention the ingredients and any garnish.
workflows:
- food
width: 1024
height: 1024
comments:
vegan:
hashtags:
- vegan
- plantbased
- crueltyfree
img_comment_usr: When provided with an image, especially one showcasing vegan food or practices, respond with a comment that combines genuine enthusiasm and positivity in the initial lines, then delivers a factual, hard-hitting truth by the third sentence. The tone should be warm and inviting, aiming to inspire others to consider the ethical and environmental implications of their everyday choices. If the image has nothing to do with veganism, animal rights, or food generally, you must respond simply with 'PASS' (in all caps).
sentiment: positive
meat:
hashtags:
- bacon
- steak
- burger
img_comment_usr: When provided with an image, especially one showcasing non-vegan food or practices, respond with a comment that combines biting sarcasm or acerbic wit in the initial lines, then delivers a factual, hard-hitting truth by the third sentence. The tone should sharply critique the ethical and environmental implications of the depicted scene, aiming to provoke thought and encourage reflection on our everyday choices. If the image has nothing to do with veganism, animal rights, or food generally, you must respond simply with 'PASS' (in all caps).
sentiment: negative
jokes:
hashtags:
- pacificnw
- pnw
- exploregon
- girlswhohike
- trend
- fashion
- science
- photography
- football
- sports
- gamenight
- gamer
- pub
- soccer
- football
- usa
- proud
- army
- patriot
- trump2024
- gop
- letsgobrandon
img_comment_usr: Make a wisecrack joke about this image. Scorch it with humor. (If that would be entirely inappropriate, you can instead respond with 'PASS', but please only pass if making a joke would be extremely distasteful).
sentiment: neutral
flattery:
hashtags:
- beauty
- latergram
- wonder
- awe
- "1440"
- pnwonderland
- vegan
- natural
- travel
- nofilter
img_comment_usr: Write a warm, gracious, upbeat, and flattering response to this Instagram post, in the tone and style befitting a very genuine modern young woman. If the content of the image or caption make it inappapropriate to comment, you may respond with 'PASS' in all capital letters, and without the quote marks, and your comment will not be posted.
sentiment: positive
openai_key: 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
ghost_admin_api_key: 65f43092d453d100019bbebf:e0cf327c04689dcfe02b65506f09d3661e8a6f0f0b564a3a55836857067d2b2c
ghost_admin_url: https://sij.ai/ghost/api/admin
ghost_content_key: 1c240344beda1bb982eb0deb38
short_sleep: 5
long_sleep: 180
img_gen: ComfyUI

View file

@ -186,8 +186,8 @@ async def process_account_archival(account: EmailAccount):
info(f"Summarized email: {uid_str}") info(f"Summarized email: {uid_str}")
else: else:
warn(f"Failed to summarize {this_email.subject}") warn(f"Failed to summarize {this_email.subject}")
else: # else:
debug(f"Skipping {uid_str} because it was already processed.") # debug(f"Skipping {uid_str} because it was already processed.")
except Exception as e: except Exception as e:
err(f"An error occurred during summarization for account {account.name}: {e}") err(f"An error occurred during summarization for account {account.name}: {e}")

View file

@ -3,12 +3,15 @@ Web server module. Used by other modules when serving static content is required
''' '''
import os import os
import io import io
import string
import json import json
import time import time
import base64 import base64
import asyncpg
import asyncio import asyncio
import subprocess import subprocess
import requests import requests
import random
import paramiko import paramiko
import aiohttp import aiohttp
import httpx import httpx
@ -18,17 +21,17 @@ from pathlib import Path
from typing import List, Optional from typing import List, Optional
from pydantic import BaseModel from pydantic import BaseModel
from PyPDF2 import PdfReader from PyPDF2 import PdfReader
from fastapi import APIRouter, Form, HTTPException, Request, Response, BackgroundTasks, status from fastapi import APIRouter, Form, HTTPException, Request, Response, BackgroundTasks, status, Path as PathParam
from fastapi.responses import FileResponse, PlainTextResponse, JSONResponse, RedirectResponse from fastapi.responses import HTMLResponse, FileResponse, PlainTextResponse, JSONResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from sijapi import ( from sijapi import (
L, API, LOGS_DIR, TS_ID, CASETABLE_PATH, COURTLISTENER_DOCKETS_URL, COURTLISTENER_API_KEY, L, API, DB, LOGS_DIR, TS_ID, CASETABLE_PATH, COURTLISTENER_DOCKETS_URL, COURTLISTENER_API_KEY,
COURTLISTENER_BASE_URL, COURTLISTENER_DOCKETS_DIR, COURTLISTENER_SEARCH_DIR, ALERTS_DIR, COURTLISTENER_BASE_URL, COURTLISTENER_DOCKETS_DIR, COURTLISTENER_SEARCH_DIR, ALERTS_DIR,
MAC_UN, MAC_PW, MAC_ID, TS_TAILNET, IMG_DIR, PUBLIC_KEY, OBSIDIAN_VAULT_DIR MAC_UN, MAC_PW, MAC_ID, TS_TAILNET, IMG_DIR, PUBLIC_KEY, OBSIDIAN_VAULT_DIR
) )
@ -36,8 +39,6 @@ from sijapi.classes import WidgetUpdate
from sijapi.utilities import bool_convert, sanitize_filename, assemble_journal_path from sijapi.utilities import bool_convert, sanitize_filename, assemble_journal_path
from sijapi.routers import gis from sijapi.routers import gis
serve = APIRouter(tags=["public"])
logger = L.get_module_logger("serve") logger = L.get_module_logger("serve")
def debug(text: str): logger.debug(text) def debug(text: str): logger.debug(text)
def info(text: str): logger.info(text) def info(text: str): logger.info(text)
@ -45,6 +46,9 @@ def warn(text: str): logger.warning(text)
def err(text: str): logger.err(text) def err(text: str): logger.err(text)
def crit(text: str): logger.critical(text) def crit(text: str): logger.critical(text)
serve = APIRouter()
templates = Jinja2Templates(directory=Path(__file__).parent.parent / "sites")
@serve.get("/pgp") @serve.get("/pgp")
async def get_pgp(): async def get_pgp():
return Response(PUBLIC_KEY, media_type="text/plain") return Response(PUBLIC_KEY, media_type="text/plain")
@ -423,3 +427,109 @@ if API.EXTENSIONS.courtlistener == "on" or API.EXTENSIONS.courtlistener == True:
await cl_download_file(download_url, target_path, session) await cl_download_file(download_url, target_path, session)
debug(f"Downloaded {file_name} to {target_path}") debug(f"Downloaded {file_name} to {target_path}")
@serve.get("/s", response_class=HTMLResponse)
async def shortener_form(request: Request):
return templates.TemplateResponse("shortener.html", {"request": request})
@serve.post("/s")
async def create_short_url(request: Request, long_url: str = Form(...), custom_code: Optional[str] = Form(None)):
async with DB.get_connection() as conn:
await conn.execute('''
CREATE TABLE IF NOT EXISTS short_urls (
short_code VARCHAR(3) PRIMARY KEY,
long_url TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
if custom_code:
if len(custom_code) != 3 or not custom_code.isalnum():
return templates.TemplateResponse("shortener.html", {"request": request, "error": "Custom code must be 3 alphanumeric characters"})
# Check if custom code already exists
existing = await conn.fetchval('SELECT 1 FROM short_urls WHERE short_code = $1', custom_code)
if existing:
return templates.TemplateResponse("shortener.html", {"request": request, "error": "Custom code already in use"})
short_code = custom_code
else:
# Generate a random 3-character alphanumeric string
chars = string.ascii_letters + string.digits
while True:
short_code = ''.join(random.choice(chars) for _ in range(3))
existing = await conn.fetchval('SELECT 1 FROM short_urls WHERE short_code = $1', short_code)
if not existing:
break
await conn.execute(
'INSERT INTO short_urls (short_code, long_url) VALUES ($1, $2)',
short_code, long_url
)
short_url = f"https://sij.ai/{short_code}"
return templates.TemplateResponse("shortener.html", {"request": request, "short_url": short_url})
@serve.get("/s", response_class=HTMLResponse)
async def shortener_form(request: Request):
return templates.TemplateResponse("shortener.html", {"request": request})
@serve.post("/s")
async def create_short_url(request: Request, long_url: str = Form(...), custom_code: Optional[str] = Form(None)):
async with DB.get_connection() as conn:
await create_short_urls_table(conn)
if custom_code:
if len(custom_code) != 3 or not custom_code.isalnum():
return templates.TemplateResponse("shortener.html", {"request": request, "error": "Custom code must be 3 alphanumeric characters"})
# Check if custom code already exists
existing = await conn.fetchval('SELECT 1 FROM short_urls WHERE short_code = $1', custom_code)
if existing:
return templates.TemplateResponse("shortener.html", {"request": request, "error": "Custom code already in use"})
short_code = custom_code
else:
# Generate a random 3-character alphanumeric string
chars = string.ascii_letters + string.digits
while True:
short_code = ''.join(random.choice(chars) for _ in range(3))
existing = await conn.fetchval('SELECT 1 FROM short_urls WHERE short_code = $1', short_code)
if not existing:
break
await conn.execute(
'INSERT INTO short_urls (short_code, long_url) VALUES ($1, $2)',
short_code, long_url
)
short_url = f"https://sij.ai/{short_code}"
return templates.TemplateResponse("shortener.html", {"request": request, "short_url": short_url})
@serve.get("/{short_code}", response_class=RedirectResponse, status_code=301)
async def redirect_short_url(request: Request, short_code: str = PathParam(..., min_length=3, max_length=3)):
if request.headers.get('host') != 'sij.ai':
raise HTTPException(status_code=404, detail="Not Found")
async with DB.get_connection() as conn:
result = await conn.fetchrow(
'SELECT long_url FROM short_urls WHERE short_code = $1',
short_code
)
if result:
return result['long_url']
else:
raise HTTPException(status_code=404, detail="Short URL not found")
async def create_short_urls_table(conn):
await conn.execute('''
CREATE TABLE IF NOT EXISTS short_urls (
short_code VARCHAR(3) PRIMARY KEY,
long_url TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')

View file

@ -0,0 +1,81 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>sij.ai URL Shortener</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
background-color: #f0f0f0;
color: #333;
}
h1 {
color: #2c3e50;
text-align: center;
}
form {
display: flex;
flex-direction: column;
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
input, button {
margin: 10px 0;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
background-color: #3498db;
color: white;
border: none;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #2980b9;
}
.error {
color: #e74c3c;
background-color: #fadbd8;
padding: 10px;
border-radius: 4px;
margin-top: 10px;
}
.success {
color: #27ae60;
background-color: #d4efdf;
padding: 10px;
border-radius: 4px;
margin-top: 10px;
}
.success a {
color: #2980b9;
text-decoration: none;
}
.success a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<h1>sij.ai URL Shortener</h1>
<form action="/s" method="post">
<input type="url" name="long_url" placeholder="Enter your long URL" required>
<input type="text" name="custom_code" placeholder="Custom code (optional, 3 characters)">
<button type="submit">Shorten URL</button>
</form>
{% if error %}
<p class="error">{{ error }}</p>
{% endif %}
{% if short_url %}
<p class="success">Your shortened URL: <a href="{{ short_url }}" target="_blank">{{ short_url }}</a></p>
{% endif %}
</body>
</html>