diff --git a/.env.example b/.env.example index 6139c2b..26cac03 100644 --- a/.env.example +++ b/.env.example @@ -2,8 +2,14 @@ POSTGRESQL_HOST=127.0.0.1 POSTGRESQL_USER=gomastodonstats POSTGRESQL_PASS="superrandompassword" POSTGRESQL_STATS_DB=gomastodonstats + +MYSQL_HOST=127.0.0.1 +MYSQL_USER=gomastodonstats +MYSQL_PASS="superrandompassword" + TIMEZONE="Pacific/Auckland" +# PostgreSQL PIXELFED_DB_SCHEMA=pixelfed MATRIX_DB_SCHEMA=matrix MASTODON_DB_SCHEMA=mastodon_production @@ -12,6 +18,9 @@ PEERTUBE_DB_SCHEMA=peertube_prod BOOKWYRM_DB_SCHEMA=bookwyrm CALCKEY_DB_SCHEMA=calckey +# MySQL +WRITEAS_DB_SCHEMA=writeas + MATRIX_WEBHOOK_URL="" MATRIX_WEBHOOK_API_KEY="" MATRIX_WEBHOOK_CHANNEL="" diff --git a/README.md b/README.md index 864a8fe..4b7ee76 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Setup a new application, use the ID/SECRET in your .env with some user creds -Create readonly account with access to stats DB +Create readonly account with access to stats DB on postgres ``` CREATE USER gomastodonstats WITH PASSWORD 'superrandompassword'; @@ -42,3 +42,9 @@ CREATE UNIQUE INDEX service_lookup ON statsdb USING btree (service,metric_name, GRANT ALL ON ALL TABLES IN SCHEMA public TO gomastodonstats; GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO gomastodonstats; ``` + +For write.as stats on MySQL +``` +create user gomastodonstats@'%' identified by ''; +grant SELECT on writeasdb.* to 'gomastodonstats'; +``` \ No newline at end of file diff --git a/cmd/gomastodonstats/main.go b/cmd/gomastodonstats/main.go index 5e71ca7..76a3f8f 100644 --- a/cmd/gomastodonstats/main.go +++ b/cmd/gomastodonstats/main.go @@ -38,9 +38,13 @@ func main() { gms.POSTGRESQL_STATS_DB = os.Getenv("POSTGRESQL_STATS_DB") if gms.POSTGRESQL_STATS_DB == "" { log.Fatal("POSTGRESQL_STATS_DB not set") - } + // Check MySQL info exists (Optional) + gms.MYSQL_HOST = os.Getenv("MYSQL_HOST") + gms.MYSQL_USER = os.Getenv("MYSQL_USER") + gms.MYSQL_PASS = os.Getenv("MYSQL_PASS") + // Load matrix data if exists, else set URL blank gms.MATRIX_WEBHOOK_URL = os.Getenv("MATRIX_WEBHOOK_URL") gms.MATRIX_WEBHOOK_API_KEY = os.Getenv("MATRIX_WEBHOOK_API_KEY") diff --git a/go.mod b/go.mod index 8b3a979..65dd3ed 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,14 @@ module gomastodonstats go 1.19 require ( + github.com/joho/godotenv v1.5.1 + github.com/lib/pq v1.10.9 + github.com/mattn/go-mastodon v0.0.6 +) + +require ( + github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/joho/godotenv v1.4.0 // indirect - github.com/lib/pq v1.10.7 // indirect - github.com/mattn/go-mastodon v0.0.6 // indirect github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect golang.org/x/text v0.6.0 // indirect ) diff --git a/go.sum b/go.sum index dd7ebb0..9af0c2c 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,15 @@ +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-mastodon v0.0.6 h1:lqU1sOeeIapaDsDUL6udDZIzMb2Wqapo347VZlaOzf0= github.com/mattn/go-mastodon v0.0.6/go.mod h1:cg7RFk2pcUfHZw/IvKe1FUzmlq5KnLFqs7eV2PHplV8= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= diff --git a/internal/gomastodonstats/consts.go b/internal/gomastodonstats/consts.go index e93e081..1c611c5 100644 --- a/internal/gomastodonstats/consts.go +++ b/internal/gomastodonstats/consts.go @@ -8,6 +8,10 @@ var ( POSTGRESQL_STATS_DB string POSTGRESQL_STATS_TABLE = "statsdb" + MYSQL_HOST string + MYSQL_USER string + MYSQL_PASS string + TIMEZONE string MATRIX_WEBHOOK_URL string @@ -34,6 +38,7 @@ var ( PEERTUBE_IDENTIFIER: "https://peertube.nz", BOOKWYRM_IDENTIFIER: "https://bookworm.nz", CALCKEY_IDENTIFIER: "https://calckey.nz", + WRITEAS_IDENTIFIER: "https://write.nz", } // Pixelfed @@ -71,4 +76,9 @@ var ( CALCKEY_DB_SCHEMA string CALCKEY_USER_QUERY = `SELECT count(*) FROM "user" WHERE "isDeleted" = False and "host" IS NULL;` CALCKEY_IDENTIFIER = "calckey" + + // Write.as + WRIETAS_DB_SCHEMA string + WRITEAS_USER_QUERY = `SELECT count(*) FROM users WHERE status = 0` + WRITEAS_IDENTIFIER = "writeas" ) diff --git a/internal/gomastodonstats/metrics.go b/internal/gomastodonstats/metrics.go index af7fe49..aa20baa 100644 --- a/internal/gomastodonstats/metrics.go +++ b/internal/gomastodonstats/metrics.go @@ -172,6 +172,23 @@ func getUserCounts() ([]metric, error) { } } + if WRIETAS_DB_SCHEMA != "" { + userCount, err := runMySqlIntQuery(WRIETAS_DB_SCHEMA, WRITEAS_USER_QUERY) + if err != nil { + log.Println(err) + } else { + m := metric{ + Service: WRITEAS_IDENTIFIER, + MetricName: METRICNAME_USERCOUNT, + MetricValue: userCount, + PreviousDayMetricValue: getLastMetric(WRITEAS_IDENTIFIER), + PreviousWeekMetricValue: getLastWeekMetric(WRITEAS_IDENTIFIER), + } + log.Printf("%s user count: %d", WRITEAS_IDENTIFIER, userCount) + metrics = append(metrics, m) + } + } + return metrics, nil } diff --git a/internal/gomastodonstats/mysql.go b/internal/gomastodonstats/mysql.go new file mode 100644 index 0000000..9885525 --- /dev/null +++ b/internal/gomastodonstats/mysql.go @@ -0,0 +1,44 @@ +package gomastodonstats + +import ( + "database/sql" + "fmt" + + _ "github.com/go-sql-driver/mysql" +) + +// Returns valid DSL for PSQL +func getMySQLConnectionString(schema string) string { + return fmt.Sprintf( + "%s:%s@%s/%s", + MYSQL_USER, + MYSQL_PASS, + MYSQL_HOST, + schema, + ) +} + +// Returns DB connection +func getMySQLConnection(schema string) (*sql.DB, error) { + return sql.Open("mysql", getMySQLConnectionString(schema)) +} + +func runMySqlIntQuery(schema string, q string) (int, error) { + var res int + db, err := getMySQLConnection(schema) + if err != nil { + return res, err + } + + rows, err := db.Query(q) + if err != nil { + return res, err + } + defer rows.Close() + + for rows.Next() { + rows.Scan(&res) + } + + return res, err +} diff --git a/internal/gomastodonstats/postgresql.go b/internal/gomastodonstats/postgresql.go index 35a0817..49731f2 100644 --- a/internal/gomastodonstats/postgresql.go +++ b/internal/gomastodonstats/postgresql.go @@ -9,7 +9,7 @@ import ( ) // Returns valid DSL for PSQL -func getConnectionString(schema string) string { +func getPostgresConnectionString(schema string) string { return fmt.Sprintf( "postgresql://%s:%s@%s/%s?sslmode=disable", POSTGRESQL_USER, @@ -20,13 +20,13 @@ func getConnectionString(schema string) string { } // Returns DB connection -func getConnection(schema string) (*sql.DB, error) { - return sql.Open("postgres", getConnectionString(schema)) +func getPostgresConnection(schema string) (*sql.DB, error) { + return sql.Open("postgres", getPostgresConnectionString(schema)) } // insertMetric to stats DB func insertValues(m metric) error { - db, err := getConnection(POSTGRESQL_STATS_DB) + db, err := getPostgresConnection(POSTGRESQL_STATS_DB) if err != nil { return err } @@ -41,7 +41,7 @@ func insertValues(m metric) error { func runIntQuery(schema string, q string) (int, error) { var res int - db, err := getConnection(schema) + db, err := getPostgresConnection(schema) if err != nil { return res, err } @@ -61,7 +61,7 @@ func runIntQuery(schema string, q string) (int, error) { func runIntQueryWithTime(schema string, q string, t time.Time) (int, error) { var res int - db, err := getConnection(schema) + db, err := getPostgresConnection(schema) if err != nil { return res, err }