social-autoposter 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -0
- package/SKILL.md +317 -0
- package/bin/cli.js +158 -0
- package/config.example.json +51 -0
- package/launchd/com.m13v.social-autoposter.plist +28 -0
- package/launchd/com.m13v.social-engage.plist +28 -0
- package/launchd/com.m13v.social-stats.plist +28 -0
- package/package.json +42 -0
- package/schema.sql +82 -0
- package/scripts/find_threads.py +194 -0
- package/scripts/scan_replies.py +370 -0
- package/scripts/update_stats.py +208 -0
- package/setup/SKILL.md +180 -0
- package/skill/SKILL.md +283 -0
- package/skill/engage.sh +109 -0
- package/skill/run.sh +41 -0
- package/skill/stats.sh +38 -0
- package/syncfield.sh +78 -0
package/syncfield.sh
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# syncfield.sh — Sync SQLite → Neon Postgres (idempotent upsert)
|
|
3
|
+
# Called after git push in stats.sh and engage.sh
|
|
4
|
+
# Requires: sqlite3, psql, DATABASE_URL in .env
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
DB="$HOME/social-autoposter/social_posts.db"
|
|
9
|
+
|
|
10
|
+
# Load secrets
|
|
11
|
+
# shellcheck source=/dev/null
|
|
12
|
+
[ -f "$HOME/social-autoposter/.env" ] && source "$HOME/social-autoposter/.env"
|
|
13
|
+
|
|
14
|
+
if [ -z "${DATABASE_URL:-}" ]; then
|
|
15
|
+
echo "syncfield: DATABASE_URL not set, skipping sync"
|
|
16
|
+
exit 0
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
TMPDIR="${TMPDIR:-/tmp}"
|
|
20
|
+
|
|
21
|
+
sync_table() {
|
|
22
|
+
local table="$1"
|
|
23
|
+
local columns="$2"
|
|
24
|
+
local conflict_col="${3:-id}"
|
|
25
|
+
local csv_file="$TMPDIR/syncfield_${table}.csv"
|
|
26
|
+
|
|
27
|
+
# Export from SQLite as CSV
|
|
28
|
+
sqlite3 -header -csv "$DB" "SELECT $columns FROM $table;" > "$csv_file"
|
|
29
|
+
|
|
30
|
+
local row_count
|
|
31
|
+
row_count=$(wc -l < "$csv_file" | tr -d ' ')
|
|
32
|
+
row_count=$((row_count - 1)) # subtract header
|
|
33
|
+
|
|
34
|
+
if [ "$row_count" -le 0 ]; then
|
|
35
|
+
rm -f "$csv_file"
|
|
36
|
+
return
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Build column list for SET clause (exclude conflict column)
|
|
40
|
+
local set_clause=""
|
|
41
|
+
IFS=',' read -ra cols <<< "$columns"
|
|
42
|
+
for col in "${cols[@]}"; do
|
|
43
|
+
col=$(echo "$col" | tr -d ' ')
|
|
44
|
+
if [ "$col" != "$conflict_col" ]; then
|
|
45
|
+
if [ -n "$set_clause" ]; then
|
|
46
|
+
set_clause="$set_clause, "
|
|
47
|
+
fi
|
|
48
|
+
set_clause="${set_clause}${col} = EXCLUDED.${col}"
|
|
49
|
+
fi
|
|
50
|
+
done
|
|
51
|
+
|
|
52
|
+
# Upsert via temp table + INSERT ON CONFLICT
|
|
53
|
+
psql "$DATABASE_URL" -q <<SQL
|
|
54
|
+
CREATE TEMP TABLE _tmp_${table} (LIKE ${table} INCLUDING ALL);
|
|
55
|
+
\\copy _tmp_${table}($columns) FROM '$csv_file' WITH (FORMAT csv, HEADER true, NULL '');
|
|
56
|
+
INSERT INTO ${table}($columns)
|
|
57
|
+
SELECT $columns FROM _tmp_${table}
|
|
58
|
+
ON CONFLICT ($conflict_col) DO UPDATE SET $set_clause;
|
|
59
|
+
DROP TABLE _tmp_${table};
|
|
60
|
+
SQL
|
|
61
|
+
|
|
62
|
+
echo "syncfield: synced $table ($row_count rows)"
|
|
63
|
+
rm -f "$csv_file"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# Sync each table
|
|
67
|
+
sync_table "posts" "id,platform,thread_url,thread_author,thread_author_handle,thread_title,thread_content,thread_engagement,our_url,our_content,our_account,posted_at,discovered_at,status,status_checked_at,engagement_updated_at,upvotes,comments_count,views,source_turn_id,source_summary,top_comment_author,top_comment_content,top_comment_upvotes,top_comment_url"
|
|
68
|
+
|
|
69
|
+
sync_table "campaigns" "id,name,prompt,platforms,status,max_posts_per_day,posts_made,created_at,updated_at"
|
|
70
|
+
|
|
71
|
+
sync_table "replies" "id,post_id,platform,their_comment_id,their_author,their_content,their_comment_url,our_reply_id,our_reply_content,our_reply_url,parent_reply_id,moltbook_post_uuid,moltbook_parent_comment_uuid,depth,status,skip_reason,discovered_at,replied_at"
|
|
72
|
+
|
|
73
|
+
sync_table "thread_comments" "id,thread_id,author,author_handle,content,engagement,discovered_at"
|
|
74
|
+
|
|
75
|
+
# Update sync timestamp
|
|
76
|
+
psql "$DATABASE_URL" -q -c "INSERT INTO _syncfield_meta (key, value) VALUES ('last_sync', NOW()::text) ON CONFLICT (key) DO UPDATE SET value = NOW()::text;"
|
|
77
|
+
|
|
78
|
+
echo "syncfield: sync complete at $(date '+%Y-%m-%d %H:%M:%S')"
|