Compare commits
20 Commits
Author | SHA1 | Date |
---|---|---|
|
120604c131 | |
|
72aa69088a | |
|
6de414d359 | |
|
97b63bfeba | |
|
0a15e0586b | |
|
5e2cabd8b7 | |
|
318b048090 | |
|
5197766815 | |
|
9ecc9a358b | |
|
c85c101b59 | |
|
ac38f8f28d | |
|
7f1938c9e5 | |
|
62c429dafb | |
|
ddf5d7f34f | |
|
8654bb13c3 | |
|
41d494eab4 | |
|
972a6226a2 | |
|
a8f4bc5e30 | |
|
5015924d19 | |
|
02b63027e2 |
21
README.md
21
README.md
|
@ -3,16 +3,21 @@ This repo contains some scripts to help automate posting live MLB game updates
|
||||||
to Mastodon.
|
to Mastodon.
|
||||||
|
|
||||||
## Structure
|
## Structure
|
||||||
|
* `mlbgames.sh`, `mlbstartpost.sh`, and `mlbfinalpost.sh` are used to make a
|
||||||
|
post at the start and end of games. `mlbgames.sh` populates the `games` table
|
||||||
|
of a SQLite database, which the play and highlight scripts read when running,
|
||||||
|
so you'll need to run `mlbgames.sh` if you want to use the other scripts.
|
||||||
* `mlbplaysave.sh` and `mlbplaypost.sh` are used in tandem to post scoring
|
* `mlbplaysave.sh` and `mlbplaypost.sh` are used in tandem to post scoring
|
||||||
updates. The former saves new plays to a SQLite database, and the latter
|
updates. The former saves new plays to a SQLite database, and the latter
|
||||||
reads the database and posts any scoring plays that have not been posted yet.
|
reads the database and posts any scoring plays that have not been posted yet.
|
||||||
* `mlbhighlightsave.sh` and `mlbhighlightpost.sh` work similarly to the
|
* `mlbhighlightsave.sh` and `mlbhighlightpost.sh` work similarly to the
|
||||||
previous pair, but post video highlights instead.
|
previous pair, but post video highlights instead.
|
||||||
* `posthighlights.sql` and `postplays.sql` are used by the posting scripts to
|
* `posthighlights.sql`, `postplays.sql`, `poststart.sql`, and `postfinal.sql`
|
||||||
select unposted data and then mark that data as posted.
|
are used by the posting scripts to select unposted data and then mark that
|
||||||
|
data as posted.
|
||||||
* `schema.sql` defines the table that new data gets saved to.
|
* `schema.sql` defines the table that new data gets saved to.
|
||||||
|
|
||||||
Note that there are invisible characters (like 0x1f) in some of the files.
|
Note that there are invisible characters (like `0x1f`) in some of the files.
|
||||||
These are used as delimiters when processing the data.
|
These are used as delimiters when processing the data.
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
@ -35,10 +40,14 @@ scripts:
|
||||||
2. Pick a directory to keep the SQLite database in (I picked
|
2. Pick a directory to keep the SQLite database in (I picked
|
||||||
`~/.local/share/mlblive`).
|
`~/.local/share/mlblive`).
|
||||||
3. Create the database with `sqlite3 <filename> < schema.sql`
|
3. Create the database with `sqlite3 <filename> < schema.sql`
|
||||||
* Note that if you intend to run both scripts, or run multiple instances of
|
* I recommend making one database for plays and one for highlights
|
||||||
the scripts, you'll probably want to make a database for each instance.
|
(assuming you wish to process both) for each team you want to follow.
|
||||||
|
Separate databases for plays and highlights will reduce delays due to locking.
|
||||||
4. Put the other SQL scripts in the same directory as the database.
|
4. Put the other SQL scripts in the same directory as the database.
|
||||||
5. Review the scripts to see what arguments they require.
|
5. Review the shell scripts to see what arguments they require.
|
||||||
6. Write some systemd services and timers to execute the shell scripts
|
6. Write some systemd services and timers to execute the shell scripts
|
||||||
automatically on some interval. Set the working directory to the directory
|
automatically on some interval. Set the working directory to the directory
|
||||||
with the database.
|
with the database.
|
||||||
|
* I have `mlbsaveplays.sh` running as a simple service, and all the other
|
||||||
|
scripts (games, highlights, `mlbpostplays.sh`) running as oneshot
|
||||||
|
services that execute on timers.
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
while getopts 'd:a:' opt
|
||||||
|
do
|
||||||
|
case $opt in
|
||||||
|
d)
|
||||||
|
db=$OPTARG
|
||||||
|
;;
|
||||||
|
a)
|
||||||
|
account=$OPTARG
|
||||||
|
;;
|
||||||
|
?)
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z $db ]]
|
||||||
|
then
|
||||||
|
echo "$0:" '-d is required' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $account ]]
|
||||||
|
then
|
||||||
|
echo "$0:" '-a is required' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# format each row of data retreived from the select statement and pipe to toot
|
||||||
|
fmt='printf "Final:\n\n%s %s\n%s %s\n\n#baseball #live\n", $1, $2, $3, $4'
|
||||||
|
post="\"toot post --using $account\""
|
||||||
|
sqlite3 $db < postfinal.sql | awk -F "{$fmt | $post; close($post)}"
|
|
@ -29,7 +29,7 @@ then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
jqFilter='.dates[].games[] | "\(.gamePk),\(.status.detailedState)"'
|
jqFilter='.dates[].games[]'
|
||||||
fmt="OFS=\",\"; print \$1, \"$team\", \$2"
|
fmt="OFS=\"\"; print \$0, 0"
|
||||||
save="\"sqlite3 $db '.import --csv /dev/stdin games'\""
|
save="\"sqlite3 $db '.mode ascii' '.separator ' '.import /dev/stdin games'\""
|
||||||
mlblive schedule -t $team | jq -r "$jqFilter" | awk -F , "{$fmt | $save; close($save)}"
|
mlblive schedule -t $team | jq -Sc "$jqFilter" | awk -F "{$fmt | $save; close($save)}"
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
while getopts 'd:a:' opt
|
||||||
|
do
|
||||||
|
case $opt in
|
||||||
|
d)
|
||||||
|
db=$OPTARG
|
||||||
|
;;
|
||||||
|
a)
|
||||||
|
account=$OPTARG
|
||||||
|
;;
|
||||||
|
?)
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z $db ]]
|
||||||
|
then
|
||||||
|
echo "$0:" '-d is required' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $account ]]
|
||||||
|
then
|
||||||
|
echo "$0:" '-a is required' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# format each row of data retreived from the select statement and pipe to toot
|
||||||
|
fmt='printf "Starting soon:\n\n%s (%s-%s) @\n%s (%s-%s)\n\n#baseball #live\n", $1, $2, $3, $4, $5, $6'
|
||||||
|
post="\"toot post --using $account\""
|
||||||
|
sqlite3 $db < poststart.sql | awk -F "{$fmt | $post; close($post)}"
|
|
@ -0,0 +1,19 @@
|
||||||
|
.separator
|
||||||
|
|
||||||
|
begin;
|
||||||
|
select
|
||||||
|
json ->> 'teams' ->> 'away' ->> 'team' ->> 'name',
|
||||||
|
json ->> 'teams' ->> 'away' ->> 'score',
|
||||||
|
json ->> 'teams' ->> 'home' ->> 'team' ->> 'name',
|
||||||
|
json ->> 'teams' ->> 'home' ->> 'score'
|
||||||
|
from games
|
||||||
|
where
|
||||||
|
json ->> 'status' ->> 'detailedState' = 'Final' and
|
||||||
|
posted = 0;
|
||||||
|
|
||||||
|
update games
|
||||||
|
set posted = 1
|
||||||
|
where
|
||||||
|
json ->> 'status' ->> 'detailedState' = 'Final' and
|
||||||
|
posted = 0;
|
||||||
|
commit;
|
|
@ -0,0 +1,21 @@
|
||||||
|
.separator
|
||||||
|
|
||||||
|
begin;
|
||||||
|
select
|
||||||
|
json ->> 'teams' ->> 'away' ->> 'team' ->> 'name',
|
||||||
|
json ->> 'teams' ->> 'away' ->> 'leagueRecord' ->> 'wins',
|
||||||
|
json ->> 'teams' ->> 'away' ->> 'leagueRecord' ->> 'losses',
|
||||||
|
json ->> 'teams' ->> 'home' ->> 'team' ->> 'name',
|
||||||
|
json ->> 'teams' ->> 'home' ->> 'leagueRecord' ->> 'wins',
|
||||||
|
json ->> 'teams' ->> 'home' ->> 'leagueRecord' ->> 'losses'
|
||||||
|
from games
|
||||||
|
where
|
||||||
|
json ->> 'status' ->> 'detailedState' = 'Warmup' and
|
||||||
|
posted = 0;
|
||||||
|
|
||||||
|
update games
|
||||||
|
set posted = 1
|
||||||
|
where
|
||||||
|
json ->> 'status' ->> 'detailedState' = 'Warmup' and
|
||||||
|
posted = 0;
|
||||||
|
commit;
|
|
@ -9,9 +9,6 @@ do
|
||||||
d)
|
d)
|
||||||
db=$OPTARG
|
db=$OPTARG
|
||||||
;;
|
;;
|
||||||
t)
|
|
||||||
team=$OPTARG
|
|
||||||
;;
|
|
||||||
?)
|
?)
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
|
@ -24,17 +21,10 @@ then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z $team ]]
|
|
||||||
then
|
|
||||||
echo "$0:" '-t is required' >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# grab the game pk of a single live game, if multiple (in case of spring
|
# grab the game pk of a single live game, if multiple (in case of spring
|
||||||
# training)
|
# training)
|
||||||
gamePk=$(sqlite3 $db "select gamePk from games where teamId='$team' and state='In Progress' limit 1")
|
gamePk=$(sqlite3 $db "select json ->> 'gamePk' from games where json ->> 'status' ->> 'detailedState' in ('In Progress', 'Game Over') limit 1")
|
||||||
if [[ -z "$gamePk" ]]
|
if [[ -z "$gamePk" ]]
|
||||||
if [[ "$gamePk" = 'null' ]]
|
|
||||||
then
|
then
|
||||||
echo "$0:" 'no live games found' >&2
|
echo "$0:" 'no live games found' >&2
|
||||||
exit 1
|
exit 1
|
|
@ -3,15 +3,12 @@
|
||||||
set -e
|
set -e
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
while getopts 'd:t:' opt
|
while getopts 'd:' opt
|
||||||
do
|
do
|
||||||
case $opt in
|
case $opt in
|
||||||
d)
|
d)
|
||||||
db=$OPTARG
|
db=$OPTARG
|
||||||
;;
|
;;
|
||||||
t)
|
|
||||||
team=$OPTARG
|
|
||||||
;;
|
|
||||||
?)
|
?)
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
|
@ -24,15 +21,9 @@ then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z $team ]]
|
|
||||||
then
|
|
||||||
echo "$0:" '-t is required' >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# grab the game pk of a single live game, if multiple (in case of spring
|
# grab the game pk of a single live game, if multiple (in case of spring
|
||||||
# training)
|
# training)
|
||||||
gamePk=$(sqlite3 $db "select gamePk from games where teamId='$team' and state in ('In Progress', 'Warmup') limit 1")
|
gamePk=$(sqlite3 $db "select json ->> 'gamePk' from games where json ->> 'status' ->> 'detailedState' in ('In Progress', 'Warmup') limit 1")
|
||||||
if [[ -z "$gamePk" ]]
|
if [[ -z "$gamePk" ]]
|
||||||
then
|
then
|
||||||
echo "$0:" 'no live games found' >&2
|
echo "$0:" 'no live games found' >&2
|
|
@ -5,9 +5,9 @@ select
|
||||||
json ->> 'description',
|
json ->> 'description',
|
||||||
json ->> 'halfInning',
|
json ->> 'halfInning',
|
||||||
json ->> 'inning',
|
json ->> 'inning',
|
||||||
json ->> 'awayTeam',
|
replace(json ->> 'awayTeam', ' ', ''),
|
||||||
json ->> 'awayScore',
|
json ->> 'awayScore',
|
||||||
json ->> 'homeTeam',
|
replace(json ->> 'homeTeam', ' ', ''),
|
||||||
json ->> 'homeScore'
|
json ->> 'homeScore'
|
||||||
from plays
|
from plays
|
||||||
where
|
where
|
18
schema.sql
18
schema.sql
|
@ -17,8 +17,18 @@ on highlights(posted)
|
||||||
where posted = 0;
|
where posted = 0;
|
||||||
|
|
||||||
create table if not exists games (
|
create table if not exists games (
|
||||||
gamePk integer,
|
"json" text unique on conflict ignore,
|
||||||
teamId text,
|
"posted" integer check ("posted" in (0, 1))
|
||||||
state text,
|
|
||||||
unique (teamId, gamePk) on conflict replace
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create index if not exists nonposted_games
|
||||||
|
on games(posted)
|
||||||
|
where posted = 0;
|
||||||
|
|
||||||
|
create trigger if not exists delete_old_states
|
||||||
|
before insert on games
|
||||||
|
begin
|
||||||
|
delete from games
|
||||||
|
where json ->> 'gamePk' = new.json ->> 'gamePk' and
|
||||||
|
json ->> 'status' ->> 'detailedState' != new.json ->> 'status' ->> 'detailedState';
|
||||||
|
end;
|
||||||
|
|
Loading…
Reference in New Issue