first commit
This commit is contained in:
commit
7176ebf63c
11 changed files with 11758 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
working-db.db3
|
||||||
|
env
|
25
Dockerfile
Normal file
25
Dockerfile
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
LABEL maintainer "J. Elfring <code@elfring.ms>"
|
||||||
|
|
||||||
|
RUN apk --no-cache --update \
|
||||||
|
add bash \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
sqlite \
|
||||||
|
&& mkdir -p /app/sequences \
|
||||||
|
&& mkdir /data
|
||||||
|
|
||||||
|
COPY sequences/Compose.db3 /app/sequences/Compose.db3
|
||||||
|
COPY compoBot.sh /app/compoBot.sh
|
||||||
|
|
||||||
|
ENV database="/data/working-db.db3" \
|
||||||
|
minWait=43200 \
|
||||||
|
maxWait=86400 \
|
||||||
|
mtdApi="https://mastodon.example/api/v1/statuses" \
|
||||||
|
mtdVisibility="direct" \
|
||||||
|
mtdToken="THIS_SHOULD_BE_A_Bearer-Token" \
|
||||||
|
|
||||||
|
VOLUME /data
|
||||||
|
WORKDIR /app
|
||||||
|
CMD ["/app/compoBot.sh"]
|
22
LICENSE.txt
Normal file
22
LICENSE.txt
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 J. Elfring
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
37
README.md
Normal file
37
README.md
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# compoBot — A bot to toot composekey sequences
|
||||||
|
The compose key (a.k.a. Multi Key) is a massively useful and
|
||||||
|
(unfortunately) forgotten feature.
|
||||||
|
It lets you type a keyboard sequence eg. `<Multi_Key><t><m>` and
|
||||||
|
it inserts a special character: ™.
|
||||||
|
|
||||||
|
This bot regularly toots one of those sequences to a mastodon
|
||||||
|
account so that everyone can appreciate them.
|
||||||
|
|
||||||
|
The sequences used, are standard on modern linux systems.
|
||||||
|
However, the compose/multikey is usually not mapped on most
|
||||||
|
keyboards.
|
||||||
|
With `xmodmap`, it can be mapped to a rarely used key like menu
|
||||||
|
or capslock.
|
||||||
|
On windows systems, there is
|
||||||
|
(WinCompose)[https://github.com/samhocevar/wincompose]
|
||||||
|
to get similar results.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
compoBot can be used from shell or docker.
|
||||||
|
The prerequisits are minimal: sqlite3, curl and the standard tools.
|
||||||
|
|
||||||
|
It is configured by environment variables wich may be set in a file
|
||||||
|
called env.
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---------------|------------------------------------------|----------------------------------------------|
|
||||||
|
| database | ./working-db.db3 /data/working-db.db3 | Databasefile, should be persistant in docker |
|
||||||
|
| minWait | 43200 (12 h) | Minimum random time to wait between toots |
|
||||||
|
| maxWait | 86400 (24 h) | Maximum random time to wait between toots |
|
||||||
|
| mtdVisibility | direct | Privacy setting for the toot¹ |
|
||||||
|
| mtdApi | https://mastodon.example/api/v1/statuses | API endpoint to sent statuses² |
|
||||||
|
| mtdToken | THIS_SHOULD_BE_A_Bearer-Token | API authentication² |
|
||||||
|
|
||||||
|
¹) https://docs.joinmastodon.org/user/posting/
|
||||||
|
²) https://docs.joinmastodon.org/methods/apps/#create-an-application
|
||||||
|
|
82
compoBot.sh
Executable file
82
compoBot.sh
Executable file
|
@ -0,0 +1,82 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#####################################################################
|
||||||
|
##
|
||||||
|
# compoBot — a bot to post compose-sequences to mastodon
|
||||||
|
# ⓒ Joerg Elfring 2020
|
||||||
|
#
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
|
||||||
|
## Databasefile
|
||||||
|
database=${database:="./working-db.db3"}
|
||||||
|
|
||||||
|
## Wait-time between toots in seconds
|
||||||
|
minWait=${minWait:=5}
|
||||||
|
maxWait=${maxWait:=10}
|
||||||
|
|
||||||
|
## Mastodon Settings&Credentials
|
||||||
|
mtdVisibility=${mtdVisibility:="direct"} # public, unlisted, private, direct.
|
||||||
|
mtdApi=${mtdApi:="https://mastodon.example/api/v1/statuses"}
|
||||||
|
mtdToken=${mtdToken:="THIS_SHOULD_BE_A_Bearer-Token"}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
test -f ./env && source ./env
|
||||||
|
|
||||||
|
echo "=============> App-Start at $(date +%Y-%m-%dT%H%M%S)"
|
||||||
|
|
||||||
|
## Blow up on errors
|
||||||
|
set -e
|
||||||
|
|
||||||
|
## Get a fresh copy of the sequence-db if it doesn't exist.
|
||||||
|
test -f $database || cp sequences/Compose.db3 $database
|
||||||
|
|
||||||
|
while true ; do
|
||||||
|
|
||||||
|
echo "-------------> Starting at $(date +%Y-%m-%dT%H%M%S)"
|
||||||
|
|
||||||
|
## Number of rows still available,
|
||||||
|
## when no row is left, we will delete the sent-table and start over
|
||||||
|
rowsAvailable=$(sqlite3 "$database" "SELECT count(keySequenceROWID) FROM stillAvailable")
|
||||||
|
echo rowsAvailable: $rowsAvailable
|
||||||
|
if [ $rowsAvailable -eq 0 ] ; then
|
||||||
|
echo "Deleting the sent-table and starting ower."
|
||||||
|
sqlite3 "$database" "DELETE from alreadySent"
|
||||||
|
fi
|
||||||
|
|
||||||
|
## Pick a random row
|
||||||
|
_keySequenceROWID=$(sqlite3 "$database" "SELECT keySequenceROWID FROM stillAvailable ORDER BY RANDOM() LIMIT 1")
|
||||||
|
_keySequence=$(sqlite3 "$database" "SELECT keySequence FROM stillAvailable WHERE keySequenceROWID=$_keySequenceROWID")
|
||||||
|
_utfCharacter=$(sqlite3 "$database" "SELECT utfCharacter FROM stillAvailable WHERE keySequenceROWID=$_keySequenceROWID")
|
||||||
|
_desc1=$(sqlite3 "$database" "SELECT desc1 FROM stillAvailable WHERE keySequenceROWID=$_keySequenceROWID")
|
||||||
|
_desc2=$(sqlite3 "$database" "SELECT desc2 FROM stillAvailable WHERE keySequenceROWID=$_keySequenceROWID")
|
||||||
|
echo "keySequenceRowID: $_keySequenceROWID"
|
||||||
|
echo "keySequence: $_keySequence"
|
||||||
|
echo "utfCharacter: $_utfCharacter"
|
||||||
|
echo "desc1: $_desc1"
|
||||||
|
echo "desc2: $_desc2"
|
||||||
|
|
||||||
|
## Pick a random phrase to start the toot
|
||||||
|
_phrase=$(sqlite3 "$database" "SELECT phrase FROM phrases ORDER BY RANDOM() LIMIT 1")
|
||||||
|
echo "phrase: $_phrase"
|
||||||
|
|
||||||
|
## Build and Send Toot
|
||||||
|
toot="$_phrase
$_keySequence
will insert $_utfCharacter
($_desc2)"
|
||||||
|
curl --form "status=$toot" \
|
||||||
|
--form "visibility=$mtdVisibility" \
|
||||||
|
--header "Authorization: Bearer $mtdToken" \
|
||||||
|
--silent \
|
||||||
|
--show-error \
|
||||||
|
$mtdApi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
## Insert sent-row into db
|
||||||
|
sqlite3 "$database" "INSERT INTO alreadySent VALUES($_keySequenceROWID, datetime('now'));"
|
||||||
|
|
||||||
|
## Sleep until the next time
|
||||||
|
waitTime=$(shuf --input-range=$minWait-$maxWait --head-count=1)
|
||||||
|
echo "Waiting for $waitTime seconds"
|
||||||
|
echo ""
|
||||||
|
sleep $waitTime
|
||||||
|
|
||||||
|
done
|
BIN
sequences/Compose.db3
Normal file
BIN
sequences/Compose.db3
Normal file
Binary file not shown.
6162
sequences/Compose.pre
Normal file
6162
sequences/Compose.pre
Normal file
File diff suppressed because it is too large
Load diff
2665
sequences/Compose.psv
Normal file
2665
sequences/Compose.psv
Normal file
File diff suppressed because it is too large
Load diff
2665
sequences/Compose.usable
Normal file
2665
sequences/Compose.usable
Normal file
File diff suppressed because it is too large
Load diff
72
sequences/README.txt
Normal file
72
sequences/README.txt
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
How to get the list of usable key-sequences?
|
||||||
|
--------------------------------------------
|
||||||
|
Download the X11 compose-sequences for en_US.UTF-8¹ and get rid of some things:
|
||||||
|
- Comments (XCOMM)
|
||||||
|
- Sequences not started my Multi_key
|
||||||
|
- Sequences containing non-standard characters
|
||||||
|
|
||||||
|
¹) en_US.UTF-8 seems to be quite complete and also available on other locales.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ wget https://cgit.freedesktop.org/xorg/lib/libX11/plain/nls/en_US.UTF-8/Compose.pre
|
||||||
|
$ grep -i '^<multi' Compose.pre | grep -v '<U....>' | grep -v 'U.....>' > Compose.usable
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Convert to psv
|
||||||
|
--------------
|
||||||
|
Plus-separated-values because + is not used in the file.
|
||||||
|
Regex to extract the fields then remove tabs and squish spaces.
|
||||||
|
TODO: There must be a better regex for this. Also, this leaves begin-of-field spaces.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sed --regexp-extended 's/(.*): \"(.*)\"(.*)#(.*)/\1+\2+\3+\4/' Compose.usable | tr -d "\t" | tr -s " " > Compose.psv
|
||||||
|
```
|
||||||
|
|
||||||
|
Load into SQLite
|
||||||
|
----------------
|
||||||
|
$ sqlite3 Compose.db3
|
||||||
|
CREATE TABLE "keySequences" (
|
||||||
|
"keySequence" TEXT NOT NULL,
|
||||||
|
"utfCharacter" TEXT NOT NULL,
|
||||||
|
"desc1" TEXT,
|
||||||
|
"desc2" TEXT
|
||||||
|
);
|
||||||
|
.mode csv
|
||||||
|
.separator "+"
|
||||||
|
.import Compose.psv keySequences
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
How to get random, unique entries that do not repeat
|
||||||
|
----------------------------------------------------
|
||||||
|
Create a table for ids we already sent.
|
||||||
|
CREATE TABLE "alreadySent" (
|
||||||
|
"keySequenceROWID" INTEGER,
|
||||||
|
"timestamp" INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
Create a view with yet unsent rows
|
||||||
|
CREATE VIEW stillAvailable (
|
||||||
|
keySequenceROWID,
|
||||||
|
keySequence,
|
||||||
|
utfCharacter,
|
||||||
|
desc1,desc2
|
||||||
|
)
|
||||||
|
AS
|
||||||
|
SELECT ROWID, keySequence, utfCharacter, desc1, desc2
|
||||||
|
FROM keySequences
|
||||||
|
WHERE ROWID NOT IN (
|
||||||
|
SELECT keySequenceROWID
|
||||||
|
FROM alreadySent
|
||||||
|
)
|
||||||
|
|
||||||
|
Add some phrases to start the toot with
|
||||||
|
---------------------------------------
|
||||||
|
Create a table with some entry-phrases:
|
||||||
|
CREATE TABLE "phrases" (
|
||||||
|
"phrase" TEXT
|
||||||
|
);
|
||||||
|
.mode csv
|
||||||
|
.separator "+"
|
||||||
|
.import phrases.txt phrases
|
26
sequences/phrases.txt
Normal file
26
sequences/phrases.txt
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
Today's compose key sequence is:
|
||||||
|
Today's compose key sequence is:
|
||||||
|
Today's compose key sequence is:
|
||||||
|
Today's compose key sequence is:
|
||||||
|
Today's compose key sequence is:
|
||||||
|
Today's compose key sequence is:
|
||||||
|
Today's compose key sequence is:
|
||||||
|
Have a key sequence:
|
||||||
|
Have a key sequence:
|
||||||
|
Have a key sequence:
|
||||||
|
With compose, exotic characters are near:
|
||||||
|
With compose, funny characters are near:
|
||||||
|
Compose key sequence:
|
||||||
|
Compose key sequence:
|
||||||
|
Compose key sequence:
|
||||||
|
Ever tried the compose key?
|
||||||
|
Ever tried the compose key?
|
||||||
|
Ever tried the compose key?
|
||||||
|
Did you know about this one?
|
||||||
|
Did you know about this one?
|
||||||
|
Check this out!
|
||||||
|
Check this out!
|
||||||
|
Check this out!
|
||||||
|
This is your daily dose of compose key sequences:
|
||||||
|
This is your daily dose of compose key sequences:
|
||||||
|
This is your daily dose of compose key sequences:
|
Loading…
Reference in a new issue