Compare commits
31 commits
ad670a8849
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 31b3b9fd24 | |||
| 37491e91e6 | |||
| 48dad0c962 | |||
| a57f1cfa71 | |||
| d30a2d7366 | |||
| 436483aac7 | |||
| cb62f179a3 | |||
| 04758f81f2 | |||
| eebe509b02 | |||
| 0bc11d85d5 | |||
| 007994e0a2 | |||
| b6a9c7e6a4 | |||
| 5f1fb1c1a4 | |||
| 05ab9425dd | |||
| d2b019f29d | |||
| fe0de738b0 | |||
| 758e4599ed | |||
| 75d482cd6b | |||
| 261f3b27ec | |||
| 11ed9e71d0 | |||
| 74b5d9b48c | |||
| feb8639213 | |||
| bad1c90d39 | |||
| dfbc17b518 | |||
| 0f701ddbe2 | |||
| 7b71469624 | |||
| abf66aa479 | |||
| e017deeaa7 | |||
| f45e1378eb | |||
| ca3b5a053c | |||
| 8ae3594c68 |
4 changed files with 248 additions and 43 deletions
31
.woodpecker/check.yml
Normal file
31
.woodpecker/check.yml
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
labels:
|
||||||
|
type: exec
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: flake check
|
||||||
|
image: bash
|
||||||
|
commands:
|
||||||
|
- nix flake check
|
||||||
|
|
||||||
|
- name: package check
|
||||||
|
image: bash
|
||||||
|
commands:
|
||||||
|
- nix build
|
||||||
|
|
||||||
|
- name: notifiy
|
||||||
|
image: bash
|
||||||
|
secrets:
|
||||||
|
- source: matrix_password
|
||||||
|
target: pass
|
||||||
|
- source: matrix_homeserver
|
||||||
|
target: address
|
||||||
|
- source: matrix_roomid
|
||||||
|
target: room
|
||||||
|
- source: matrix_username
|
||||||
|
target: user
|
||||||
|
commands:
|
||||||
|
- nix run .
|
||||||
|
when:
|
||||||
|
status:
|
||||||
|
- failure
|
||||||
|
- success
|
||||||
34
README.md
Normal file
34
README.md
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# matrix-notifier
|
||||||
|
|
||||||
|
This is a simple to send a message to a Matrix room. It automatically logs in
|
||||||
|
and sends the message when invoked. This was written to be used a notification
|
||||||
|
script in my CI/CD pipelines.
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
You need to define the following environment variables for the script to be
|
||||||
|
executed correctly:
|
||||||
|
|
||||||
|
* `USER`: the user to login as.
|
||||||
|
* `PASS`: the password to login with.
|
||||||
|
* `ADDRESS`: the address of the homeserver to connect to.
|
||||||
|
* `ROOM`: the room id, as can be found in the room parameters.
|
||||||
|
* `MESSAGE`: the message you wish to send to the room.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export ADDRESS='https://matrix.org'
|
||||||
|
export USER='username'
|
||||||
|
export PASS='password'
|
||||||
|
export ROOM='!aaaaaaaaaaaaaaaaaa:matrix.org'
|
||||||
|
export MESSAGE='This is my test message'
|
||||||
|
./matrix-notifier
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to run/install
|
||||||
|
|
||||||
|
This script is packaged with `Nix`, you can just use `nix run .` to run it.
|
||||||
|
|
||||||
|
The only dependencies are `bash`, `curl`, and `jq`, install those and you should
|
||||||
|
be ready to go! Format is needed when using formatting (enabled by default).
|
||||||
40
flake.nix
40
flake.nix
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
description = "Ambroisie's blog";
|
description = "A simple Matrix notifier for CI purposes";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
futils = {
|
futils = {
|
||||||
|
|
@ -36,6 +36,8 @@
|
||||||
in
|
in
|
||||||
rec {
|
rec {
|
||||||
apps = {
|
apps = {
|
||||||
|
default = apps.matrix-notifier;
|
||||||
|
|
||||||
matrix-notifier =
|
matrix-notifier =
|
||||||
futils.lib.mkApp { drv = packages.matrix-notifier; };
|
futils.lib.mkApp { drv = packages.matrix-notifier; };
|
||||||
};
|
};
|
||||||
|
|
@ -56,26 +58,24 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
defaultApp = apps.matrix-notifier;
|
devShells = {
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
name = "matrix-notifier";
|
||||||
|
|
||||||
defaultPackage = packages.matrix-notifier;
|
inputsFrom = with self.packages.${system}; [
|
||||||
|
matrix-notifier
|
||||||
|
];
|
||||||
|
|
||||||
devShell = pkgs.mkShell {
|
inherit (self.checks.${system}.pre-commit) shellHook;
|
||||||
name = "matrix-notifier";
|
};
|
||||||
|
|
||||||
buildInputs = with pkgs; [
|
|
||||||
curl
|
|
||||||
jq
|
|
||||||
shellcheck
|
|
||||||
];
|
|
||||||
|
|
||||||
inherit (self.checks.${system}.pre-commit) shellHook;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = {
|
packages = {
|
||||||
|
default = packages.matrix-notifier;
|
||||||
|
|
||||||
matrix-notifier = pkgs.stdenvNoCC.mkDerivation rec {
|
matrix-notifier = pkgs.stdenvNoCC.mkDerivation rec {
|
||||||
pname = "matrix-notifier";
|
pname = "matrix-notifier";
|
||||||
version = "0.1.0";
|
version = "0.4.0";
|
||||||
|
|
||||||
src = ./matrix-notifier;
|
src = ./matrix-notifier;
|
||||||
|
|
||||||
|
|
@ -99,12 +99,24 @@
|
||||||
wrapperPath = with pkgs; lib.makeBinPath [
|
wrapperPath = with pkgs; lib.makeBinPath [
|
||||||
curl
|
curl
|
||||||
jq
|
jq
|
||||||
|
pandoc
|
||||||
];
|
];
|
||||||
|
|
||||||
fixupPhase = ''
|
fixupPhase = ''
|
||||||
patchShebangs $out/bin/${pname}
|
patchShebangs $out/bin/${pname}
|
||||||
wrapProgram $out/bin/${pname} --prefix PATH : "${wrapperPath}"
|
wrapProgram $out/bin/${pname} --prefix PATH : "${wrapperPath}"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
description = ''
|
||||||
|
A very simple bash script that can be used to send a message to
|
||||||
|
a Matrix room
|
||||||
|
'';
|
||||||
|
homepage = "https://gitea.belanyi.fr/ambroisie/${pname}";
|
||||||
|
license = licenses.mit;
|
||||||
|
platforms = platforms.unix;
|
||||||
|
maintainers = with maintainers; [ ambroisie ];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
186
matrix-notifier
186
matrix-notifier
|
|
@ -4,6 +4,21 @@ print_err() {
|
||||||
printf "%s\n" "$1" >&2
|
printf "%s\n" "$1" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
print_err "Usage: $0 [option]..."
|
||||||
|
print_err ""
|
||||||
|
print_err " -h, --help"
|
||||||
|
print_err " print this usage screen and exit"
|
||||||
|
print_err " -f, --format"
|
||||||
|
print_err " should the message be formatted using 'pandoc'."
|
||||||
|
print_err " Must be either 'true' or 'false'."
|
||||||
|
print_err " -t, --type"
|
||||||
|
print_err " which message type should be sent must be one of"
|
||||||
|
print_err " 'text' or 'notice', or 'auto'."
|
||||||
|
print_err " The special value 'auto' defaults to 'notice', unless"
|
||||||
|
print_err " 'CI_PIPELINE_STATUS'/'DRONE_BUILD_STATUS' indicates a failure."
|
||||||
|
}
|
||||||
|
|
||||||
# Blessed Stack Overflow
|
# Blessed Stack Overflow
|
||||||
rawurlencode() {
|
rawurlencode() {
|
||||||
(set +x
|
(set +x
|
||||||
|
|
@ -23,37 +38,150 @@ rawurlencode() {
|
||||||
echo "$encoded")
|
echo "$encoded")
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -z "$USER" ] || [ -z "$PASS" ]; then
|
default_woodpecker_message() {
|
||||||
print_err "You must provide USER and PASS"
|
local msg="Build ${CI_PIPELINE_STATUS}"
|
||||||
exit 1
|
local woodpecker_url="${CI_PIPELINE_URL}"
|
||||||
elif [ -z "$ADDRESS" ] || [ -z "$ROOM" ]; then
|
if [ "$FORMAT" == "true" ]; then
|
||||||
print_err "You must provide ADDRESS and ROOM"
|
msg="$msg [${CI_REPO}#${CI_COMMIT_SHA:0:8}]($woodpecker_url)"
|
||||||
exit 1
|
else
|
||||||
elif [ -z "$MESSAGE" ]; then
|
msg="$msg $woodpecker_url"
|
||||||
print_err "You must provide MESSAGE"
|
fi
|
||||||
exit 1
|
msg="$msg (${CI_COMMIT_TAG:-$CI_COMMIT_BRANCH})"
|
||||||
fi
|
printf '%s' "$msg"
|
||||||
|
}
|
||||||
|
|
||||||
if [ "$(curl -XGET "$ADDRESS/_matrix/client/r0/login" 2>/dev/null |
|
default_drone_message() {
|
||||||
jq 'any(.flows[].type; .== "m.login.password")')" != "true" ]; then
|
local msg="Build ${DRONE_BUILD_STATUS}"
|
||||||
print_err "Login method not supported"
|
local drone_url="${DRONE_SYSTEM_PROTO}://${DRONE_SYSTEM_HOST}/${DRONE_REPO}/${DRONE_BUILD_NUMBER}"
|
||||||
exit 1
|
if [ "$FORMAT" == "true" ]; then
|
||||||
fi
|
msg="$msg [${DRONE_REPO_OWNER}/${DRONE_REPO_NAME}#${DRONE_COMMIT:0:8}]($drone_url)"
|
||||||
|
else
|
||||||
|
msg="$msg $drone_url"
|
||||||
|
fi
|
||||||
|
msg="$msg (${DRONE_TAG:-$DRONE_BRANCH})"
|
||||||
|
printf '%s' "$msg"
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_variables() {
|
||||||
|
if [ "$CI" == "woodpecker" ] && [ -z "$MESSAGE" ]; then
|
||||||
|
MESSAGE="$(default_woodpecker_message)"
|
||||||
|
elif [ "$DRONE" == "true" ] && [ -z "$MESSAGE" ]; then
|
||||||
|
MESSAGE="$(default_drone_message)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$USER" ] || [ -z "$PASS" ]; then
|
||||||
|
print_err "You must provide USER and PASS"
|
||||||
|
exit 1
|
||||||
|
elif [ -z "$ADDRESS" ] || [ -z "$ROOM" ]; then
|
||||||
|
print_err "You must provide ADDRESS and ROOM"
|
||||||
|
exit 1
|
||||||
|
elif [ -z "$MESSAGE" ]; then
|
||||||
|
print_err "You must provide MESSAGE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_message_type() {
|
||||||
|
if [ "$MSG_TYPE" == "auto" ]; then
|
||||||
|
if [ "$CI_PIPELINE_STATUS" == "failure" ]; then
|
||||||
|
MSG_TYPE="text"
|
||||||
|
elif [ "$DRONE_BUILD_STATUS" == "failure" ]; then
|
||||||
|
MSG_TYPE="text"
|
||||||
|
else
|
||||||
|
MSG_TYPE="notice"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s' "m.$MSG_TYPE"
|
||||||
|
}
|
||||||
|
|
||||||
|
make_message_json() {
|
||||||
|
{
|
||||||
|
printf '%s' "$1" |
|
||||||
|
jq --raw-input --slurp "{msgtype: \"$(get_message_type)\", body: .}"
|
||||||
|
[ "$FORMAT" == "true" ] && printf '%s' "$1" |
|
||||||
|
pandoc |
|
||||||
|
jq --raw-input --slurp "{format: \"org.matrix.custom.html\", formatted_body: .}"
|
||||||
|
} | jq -s 'add'
|
||||||
|
}
|
||||||
|
|
||||||
|
send_message() {
|
||||||
|
local login_json
|
||||||
|
local token
|
||||||
|
local message_json
|
||||||
|
|
||||||
|
if [ "$(curl -XGET "$ADDRESS/_matrix/client/r0/login" 2>/dev/null |
|
||||||
|
jq 'any(.flows[].type; .== "m.login.password")')" != "true" ]; then
|
||||||
|
print_err "Login method not supported"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
LOGIN_JSON="$(printf '%s\n%s' "$USER" "$PASS" |
|
login_json="$(printf '%s\n%s' "$USER" "$PASS" |
|
||||||
jq -Rn '[inputs] | {type: "m.login.password", user: .[0], password: .[1]}')" &>/dev/null
|
jq -Rn '[inputs] | {type: "m.login.password", user: .[0], password: .[1]}')" &>/dev/null
|
||||||
TOKEN="$(curl -XPOST \
|
token="$(curl -XPOST \
|
||||||
-d "$LOGIN_JSON" \
|
-d "$login_json" \
|
||||||
"$ADDRESS/_matrix/client/r0/login" 2>/dev/null| jq .access_token --raw-output)"
|
"$ADDRESS/_matrix/client/r0/login" 2>/dev/null| jq .access_token --raw-output)"
|
||||||
|
|
||||||
if [ -z "$TOKEN" ] || [ "$TOKEN" == "null" ]; then
|
if [ -z "$token" ] || [ "$token" == "null" ]; then
|
||||||
print_err "Error during login"
|
print_err "Error during login"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MESSAGE_JSON="$(printf '%s' "$MESSAGE" |
|
message_json="$(make_message_json "$MESSAGE")"
|
||||||
jq --raw-input --slurp '{msgtype: "m.text", body: .}')"
|
curl -XPOST \
|
||||||
curl -XPOST \
|
-d "$message_json" \
|
||||||
-d "$MESSAGE_JSON" \
|
"$ADDRESS/_matrix/client/r0/rooms/$(rawurlencode "$ROOM")/send/m.room.message?access_token=$(rawurlencode "$token")" 2>/dev/null
|
||||||
"$ADDRESS/_matrix/client/r0/rooms/$(rawurlencode "$ROOM")/send/m.room.message?access_token=$(rawurlencode "$TOKEN")" 2>/dev/null
|
}
|
||||||
|
|
||||||
|
MSG_TYPE='auto'
|
||||||
|
FORMAT='true'
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
opt="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
case "$opt" in
|
||||||
|
-f|--format)
|
||||||
|
arg="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ "$arg" == "true" ] || [ "$arg" == "false" ]; then
|
||||||
|
FORMAT="$arg"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_err "Must give value 'true' or 'false' with '-t|--type'"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
-t|--type)
|
||||||
|
arg="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ -z "$arg" ]; then
|
||||||
|
print_err "Must give a message type when using '-t|--type'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for type in text notice auto; do
|
||||||
|
if [ "$arg" == "$type" ]; then
|
||||||
|
continue 2 # Go to next argument
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
print_err "Invalid message type '$arg'"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
print_err "Unknown argument '$opt'"
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
ensure_variables
|
||||||
|
send_message
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue