Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added sendToTelegram in proxy and notifier #232

Open
wants to merge 30 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
21db2fd
Added sendToTelegram in proxy and notifier
phillamy Nov 4, 2021
54d53dc
Removed test keys
phillamy Nov 4, 2021
90ce08a
Added Telegram feature in setup + test on CN start
phillamy Nov 10, 2021
fdcd7ef
undo change
phillamy Nov 10, 2021
4ad3840
undo change
phillamy Nov 10, 2021
9a155b9
removed empty line
phillamy Nov 10, 2021
d3f11d9
move test in tests directory
phillamy Nov 15, 2021
6ce3bd5
Added TG config to setup
phillamy Nov 21, 2021
66b6788
renamed prompter file notifier
phillamy Nov 21, 2021
f2d7fe5
minor fix
phillamy Nov 21, 2021
ff55bd4
added comment + modified trace
phillamy Nov 22, 2021
5ae063c
Merge remote-tracking branch 'upstream/dev' into features/telegram
phillamy Jan 6, 2022
c4dd86b
fix filename conflict after merge
phillamy Jan 6, 2022
b41c840
Removed notifier datapath and added dist/.env
phillamy Jan 8, 2022
29a7551
extra-comma removed
phillamy Jan 8, 2022
1830eed
Merge remote-tracking branch 'upstream/dev' into features/telegram
phillamy Apr 12, 2022
201b498
Added TG config script
phillamy Apr 15, 2022
62d6cf3
Reload configs at the end of TG setup via MQTT
phillamy May 3, 2022
0b17292
moved setup scripts in notifier
phillamy May 3, 2022
fd07ba8
Merge remote-tracking branch 'upstream/dev' into features/telegram
phillamy May 3, 2022
2f0ccbb
moved ssetup in notifier
phillamy May 3, 2022
5e45952
fix a merge fu
phillamy May 3, 2022
fa4bf60
Test TG only once
phillamy May 3, 2022
b94e884
new doc for setting up TG
phillamy May 3, 2022
f414868
Merge branch 'features/telegram' of github.com:phillamy/cyphernode in…
phillamy May 3, 2022
d0799cf
wait loop able creation + readLoop in notifier
phillamy May 4, 2022
d7ae529
Merge remote-tracking branch 'upstream/dev' into features/telegram
phillamy May 12, 2022
f6459a3
tor config
phillamy May 12, 2022
7dffd37
Hooked up TG setup in start.sh
phillamy May 12, 2022
165b0c8
TG setup with a nicer look - added colors
phillamy May 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
.vscode
dist/**
!dist/setup.sh
!dist/sr.sh
!dist/sr.sh
4 changes: 4 additions & 0 deletions cyphernodeconf_docker/features.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
{
"name": "Specter Cypherapp",
"value": "specter"
},
{
"name": "Telegram notifications",
"value": "telegram"
}
]
1 change: 1 addition & 0 deletions cyphernodeconf_docker/help.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@
"installer_mode": "Only one <font underline='true'>installation mode</font> is supported, right now: <font color='#0000ff'>local docker (self-hosted)</font>. Choose wisely ;-)",
"installer_cleanup": "Do you want to <font underline='true'>remove</font> this configurator Docker image after installation? This would free about 150MB of disk space.",
"docker_mode": "Cyphernode Docker services can be run using <font underline='true'>Docker Swarm</font> (https://docs.docker.com/engine/swarm/) or <font underline='true'>docker-compose</font> (https://docs.docker.com/compose/overview/). Both will work, some users prefer one to another depending on deployment types, scalability, current framework, etc.",
"telegram": "Would you like to enable Telegram notifications - Some manual steps need to be carried once before first use. See /notifier_docker/sample-config.sh",
"__default__": ""
}
4 changes: 4 additions & 0 deletions cyphernodeconf_docker/lib/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,10 @@ module.exports = class App {
clearnet: !this.isChecked('features', 'tor') || this.isChecked('clearnet', 'clearnet_lightning'),
tor_hostname: this.sessionData.tor_lightning_hostname
}
},
telegram: {
networks: ['cyphernodenet'],
docker: "cypernode/notifier"
}
}

Expand Down
27 changes: 27 additions & 0 deletions cyphernodeconf_docker/prompters/300_notifier.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const chalk = require('chalk');

const name = 'notifier';

const capitalise = function( txt ) {
return txt.charAt(0).toUpperCase() + txt.substr(1);
};

const prefix = function() {
return chalk.green(capitalise(name)+': ');
};

const featureCondition = function(props) {
return props.features && props.features.indexOf( 'telegram' ) != -1;
};

module.exports = {
name: function() {
return name;
},
prompts: function( utils ) {
return [];
},
templates: function( props ) {
return [ 'notifier.env' ];
}
};
6 changes: 4 additions & 2 deletions cyphernodeconf_docker/schema/config-v0.2.6.json
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@
"lightning",
"otsclient",
"batcher",
"specter"
"specter",
"telegram"
],
"title": "The feature",
"default": "",
Expand All @@ -198,7 +199,8 @@
"lightning",
"otsclient",
"batcher",
"specter"
"specter",
"telegram"
]
}
},
Expand Down
1 change: 1 addition & 0 deletions cyphernodeconf_docker/templates/installer/config.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
INSTALLER_MODE=<%= installer_mode %>
BITCOIN_INTERNAL=<%= (bitcoin_mode==="internal"?'true':'false') %>
FEATURE_LIGHTNING=<%= (features.indexOf('lightning') != -1)?'true':'false' %>
FEATURE_TELEGRAM=<%= (features.indexOf('telegram') != -1)?'true':'false' %>
FEATURE_BATCHER=<%= (features.indexOf('batcher') != -1)?'true':'false' %>
FEATURE_SPECTER=<%= (features.indexOf('specter') != -1)?'true':'false' %>
FEATURE_OTSCLIENT=<%= (features.indexOf('otsclient') != -1)?'true':'false' %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,14 @@ services:
- .env/notifier.env
volumes:
- "<%= logs_datapath %>:/cnlogs"
- "<%= proxy_datapath %>:/proxy/db"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this for pgpass? Let's only mount that specific file... and not in /proxy/db but something more relevant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Will do

- container_monitor:/container_monitor
networks:
- cyphernodenet
- cyphernodeappsnet
depends_on:
- broker
- postgres
<% if ( docker_mode === 'swarm' ) { %>
deploy:
replicas: 1
Expand Down
36 changes: 35 additions & 1 deletion cyphernodeconf_docker/templates/installer/testfeatures.sh
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,23 @@ checknotifier() {
return 0
}

checknotifiertelegram() {
echo -en "\r\n\e[1;36mTesting Notifier Telegram... " > /dev/console
local response
local returncode

response=$(mosquitto_rr -h broker -W 15 -t notifier -e "response/$$" -m "{\"response-topic\":\"response/$$\",\"cmd\":\"sendToTelegramNoop\"}")
returncode=$?
[ "${returncode}" -ne "0" ] && return 115
http_code=$(echo "${response}" | jq -r ".http_code")
[ "${http_code}" -ge "400" ] && return 118
[ "${http_code}" -eq "0" ] && return 119

echo -e "\e[1;36mNotifier Telegram rocks!" > /dev/console

return 0
}

checkots() {
echo -en "\r\n\e[1;36mTesting OTSclient... " > /dev/console
local rc
Expand Down Expand Up @@ -306,7 +323,7 @@ if [ "${returncode}" -ne "0" ]; then
workingproxy="false"
fi
else
echo -e "\e[1;36mCyphernode seems to be correctly deployed. Let's run more thourough tests..." > /dev/console
echo -e "\e[1;36mCyphernode seems to be correctly deployed. Let's run more thorough tests..." > /dev/console
fi

# Let's now check each feature fonctionality...
Expand Down Expand Up @@ -405,6 +422,23 @@ fi
finalreturncode=$((${returncode} | ${finalreturncode}))
result="${result}$(feature_status ${returncode} 'Notifier error!')}"

<% if (features.indexOf('telegram') != -1) { %>
#############################
# NOTIFIER TELEGRAM #
#############################

result="${result},{\"coreFeature\":true, \"name\":\"notifier telegram\",\"working\":"
status=$(echo "{${containers}}" | jq ".containers[] | select(.name == \"notifier\") | .active")
if [[ "${workingproxy}" = "true" && "${status}" = "true" ]]; then
timeout_feature checknotifiertelegram
returncode=$?
else
returncode=1
fi
finalreturncode=$((${returncode} | ${finalreturncode}))
result="${result}$(feature_status ${returncode} 'Notifier Telegram error!')}"
<% } %>

#############################
# PYCOIN #
#############################
Expand Down
5 changes: 5 additions & 0 deletions cyphernodeconf_docker/templates/notifier/notifier.env
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@ TRACING=1
TOR_HOST=tor
TOR_PORT=9050
<% } %>

<% if ( features.indexOf('telegram') !== -1 ) { %>
FEATURE_TELEGRAM=true
<% } %>
PGPASSFILE=/proxy/db/pgpass
10 changes: 9 additions & 1 deletion dist/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,6 @@ install_docker() {
copy_file $cyphernodeconf_filepath/otsclient/otsclient.env $current_path/.env/otsclient.env 1 $SUDO_REQUIRED
copy_file $cyphernodeconf_filepath/proxycron/proxycron.env $current_path/.env/proxycron.env 1 $SUDO_REQUIRED


if [[ $BITCOIN_INTERNAL == true ]]; then
if [ ! -d $BITCOIN_DATAPATH ]; then
step " create $BITCOIN_DATAPATH"
Expand Down Expand Up @@ -856,6 +855,15 @@ install_apps() {
next
fi
fi

if [[ $FEATURE_TELEGRAM == true ]]; then
step " enabled Telegram - Manual configuration needed before first time use (Bot and Group creation, API key) - see doc/TELEGRAM.md"
next
else
step " disabled Telegram"
next
fi

}

install() {
Expand Down
81 changes: 81 additions & 0 deletions doc/TELEGRAM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Telegram integration in Cyphernode.

Build and setup Cyphernode - Choose to enable Telegram. The first time you run Cyphernode, you will get an error concerning Telegram beacause Telegram has to be setup with the next few steps.

START CYPHERNODE running /dist/start.sh

In directory cyphernode/notifier_docker/scripts, you will find the script start-tg-setup.sh to start the Telegram setup. It runs inside the notifier container with this command :
docker exec -it $(docker ps -q -f "name=cyphernode_notifier") ./tgsetup.sh

Follow the steps of the installer - example output follows:

notifier_docker/script % ./start-tg-setup.sh
Testing database before starting the configuration
Database is alive
Do you wish to configure Telegram for Cyphernode? [yn] yAdding the Telegram base URL in database config table cyphernode_props
[sql] psql -qAtX -h postgres -U cyphernode -c "INSERT INTO cyphernode_props (category, property, value) VALUES ('notifier', 'tg_base_url', 'https://api.telegram.org/bot') ON CONFLICT (category, property) DO NOTHING"
0

Please go into your Telegram App and start chatting with the @BotFather

==> (Step 1) Enter @Botfather in the search tab and choose this bot
==> Note, official Telegram bots have a blue checkmark beside their name
==> (Step 2) Click “Start” to activate BotFather bot. In response, you receive a list of commands to manage bots
==> (Step 3) Choose or type the /newbot command and send it
==> @BotFather replies: Alright, a new bot. How are we going to call it? Please choose a name for your bot
==> (Step 4) Choose a name for your bot. And choose a username for your bot — the bot can be found by its username in searches. The username must be unique and end with the word 'bot'
==> After you choose a suitable name for your bot — the bot is created. You will receive a message with a link to your bot t.me/<bot_username>
==> Cyphernode needs the generated token to access the API: Copy the line below following the message 'Use this token to access the HTTP API'
Enter the token here: 5172851233:AAHkpd4T1ILyhXyqDelNnOTgFE4hl-AQSVMTelegram Setup will now try to obtain the chat ID from the Telgram server.
To make this happen, please go into the Telegram App and send a message to the new bot
Click on the link in the @BotFather's answer : Congratulations on your new bot. You will find it at t.me/your-new-bot.
Trying to contact Telegram server...
[sql] psql -qAtX -h postgres -U cyphernode -c "INSERT INTO cyphernode_props (category, property, value) VALUES ('notifier', 'tg_api_key', '3172855133:AAHkpd4T1ILyhXyqDelNnOTgFE4hl-AQSVM') ON CONFLICT (category, property) DO UPDATE SET value='5182851733:AAHkpd4T1ILyhXyqDelNnOTgFE4hl-AQSVM'"
0
[sql] psql -qAtX -h postgres -U cyphernode -c "INSERT INTO cyphernode_props (category, property, value) VALUES ('notifier', 'tg_chat_id', '1649436203') ON CONFLICT (category, property) DO UPDATE SET value=1609936104"
0

Reloading configs

Sending message to Telegram [Tue May 3 16:29:03 UTC 2022]
Ok. Done.









How it works :

calling Telegram API
example :
https://api.telegram.org/bot+TELEGRAM_API_KEY/your-action
https://api.telegram.org/botTELEGRAM_API_KEY/getMe
returns:
{"ok":true,"result":{"id":2084591315,"is_bot":true,"first_name":"Roger-logger","username":"RogerLoggerBot","can_join_groups":true,"can_read_all_group_messages":false,"supports_inline_queries":false}}

Add your Bot to a group and then get updates to get the chat.ID in order to send messages to this group afterwards.
Below, the chat.id is chat.id:-TELEGRAM_CHAT_ID

https://api.telegram.org/botTELEGRAM_API_KEY/getUpdates

{"ok":true,"result":[{"update_id":701180871,
#"my_chat_member":{"chat":{"id":-TELEGRAM_CHAT_ID,"title":"Logging","type":"group","all_members_are_administrators":false},"from":{"id":1609436204,"is_bot":false,"first_name":"Roger","last_name":"Brulotte","username":"RogerBrulotte","language_code":"en"},"date":1635877254,"old_chat_member":{"user":{"id":2084591315,"is_bot":true,"first_name":"Roger-logger","username":"RogerLoggerBot"},"status":"member"},"new_chat_member":{"user":{"id":2084591315,"is_bot":true,"first_name":"Roger-logger","username":"RogerLoggerBot"},"status":"left"}}},{"update_id":701180872,
#"message":{"message_id":7,"from":{"id":1609436204,"is_bot":false,"first_name":"Roger","last_name":"Brulotte","username":"RogerBrulotte","language_code":"en"},"chat":{"id":-TELEGRAM_CHAT_ID,"title":"Logging","type":"group","all_members_are_administrators":true},"date":1635877254,"left_chat_participant":{"id":2084591315,"is_bot":true,"first_name":"Roger-logger","username":"RogerLoggerBot"},"left_chat_member":{"id":2084591315,"is_bot":true,"first_name":"Roger-logger","username":"RogerLoggerBot"}}},{"update_id":701180873,
#"my_chat_member":{"chat":{"id":-TELEGRAM_CHAT_ID,"title":"Logging","type":"group","all_members_are_administrators":true},"from":{"id":1609436204,"is_bot":false,"first_name":"Roger","last_name":"Brulotte","username":"RogerBrulotte","language_code":"en"},"date":1635877290,"old_chat_member":{"user":{"id":2084591315,"is_bot":true,"first_name":"Roger-logger","username":"RogerLoggerBot"},"status":"left"},"new_chat_member":{"user":{"id":2084591315,"is_bot":true,"first_name":"Roger-logger","username":"RogerLoggerBot"},"status":"member"}}},{"update_id":701180874,
#"message":{"message_id":8,"from":{"id":1609436204,"is_bot":false,"first_name":"Roger","last_name":"Brulotte","username":"RogerBrulotte","language_code":"en"},"chat":{"id":-TELEGRAM_CHAT_ID,"title":"Logging","type":"group","all_members_are_administrators":true},"date":1635877290,"new_chat_participant":{"id":2084591315,"is_bot":true,"first_name":"Roger-logger","username":"RogerLoggerBot"},"new_chat_member":{"id":2084591315,"is_bot":true,"first_name":"Roger-logger","username":"RogerLoggerBot"},"new_chat_members":[{"id":2084591315,"is_bot":true,"first_name":"Roger-logger","username":"RogerLoggerBot"}]}}]}

Bot says Hello World using the chat id returned previously
https://api.telegram.org/botTOKEN/sendMessage?chat_id=CHAT-ID&text=Hello+World
https://api.telegram.org/botTELEGRAM_API_KEY/sendMessage?chat_id=-TELEGRAM_CHAT_ID&text=Hello+World

returns:
{"ok":true,"result":{"message_id":9,"from":{"id":2084591315,"is_bot":true,"first_name":"Roger-logger","username":"RogerLoggerBot"},"chat":{"id":-TELEGRAM_CHAT_ID,"title":"Logging","type":"group","all_members_are_administrators":true},"date":1635877783,"text":"Hello World"}}



curl POST example
curl -X POST https://api.telegram.org/botTELEGRAM_API_KEY/sendMessage?chat_id=TELEGRAM_CHAT_ID -H 'Content-Type: application/json' -d '{"text":"text in POST data"}'
2 changes: 1 addition & 1 deletion notifier_docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM eclipse-mosquitto:1.6-openssl

ENV HOME /notifier

RUN apk --no-cache --update add jq curl su-exec
RUN apk --no-cache --update add jq curl su-exec postgresql

WORKDIR ${HOME}

Expand Down
78 changes: 78 additions & 0 deletions notifier_docker/script/requesthandler.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
. ./trace.sh
. ./web.sh
. ./response.sh
. ./sql.sh

main() {
trace "Entering main()..."
Expand All @@ -11,6 +12,13 @@ main() {
local cmd
local response
local response_topic
local url

TG_BOT_URL=""
TG_API_KEY=""
TG_CHAT_ID=""

loadConfig

# Messages should have this form:
# {"response-topic":"response/5541","cmd":"web","url":"2557df870b9a:1111/callback1conf","body":"eyJpZCI6IjUxIiwiYWRkc...dCI6MTUxNzYwMH0K"}
Expand All @@ -29,11 +37,81 @@ main() {
response=$(web "${msg}")
publish_response "${response}" "${response_topic}" ${?}
;;
sendToTelegramGroup)
# example:
# local body=$(echo "{\"text\":\"Hello world in Telegram at `date -u +"%FT%H%MZ"`\"}" | base64)
# response=$(mosquitto_rr -h broker -W 15 -t notifier -e "response/$$" -m "{\"response-topic\":\"response/$$\",\"cmd\":\"sendToTelegramGroup\",\"body\":\"${body}\"}")
if [ "${FEATURE_TELEGRAM}" = "true" ]; then
url=$(echo ${TG_BOT_URL}${TG_API_KEY}/sendMessage?chat_id=${TG_CHAT_ID})
trace "[main] telegram-url=${url}"

msg=$(echo ${msg} | jq --arg url ${url} '. += {"url":$url}' )
trace "[main] web-msg=${msg}"

response=$(web "${msg}")
publish_response "${response}" "${response_topic}" ${?}
else
trace "[main] Telegram is NOT enabled - message not sent"
fi
;;
sendToTelegramNoop)
if [ "${FEATURE_TELEGRAM}" = "true" ]; then
url=$(echo ${TG_BOT_URL}${TG_API_KEY}/getMe)
trace "[main] telegram-url=${url}"

msg=$(echo ${msg} | jq --arg url ${url} '. += {"url":$url}' )
trace "[main] web-msg=${msg}"

response=$(web "${msg}")
publish_response "${response}" "${response_topic}" ${?}
else
trace "[main] Telegram is NOT enabled - message not sent"
fi
;;
reloadConfig)
trace "[main] Reloading configs Now"
response="{\"return_code\":\"$(loadConfig)\"}"
trace "[main] response=${response}"
publish_response "${response}" "${response_topic}" ${?}
trace "[main] Reloading configs - Done"
;;
esac
trace "[main] msg processed"
done
}

loadConfig(){
if [ "${FEATURE_TELEGRAM}" = "true" ]; then
trace "[loadConfig] FEATURE_TELEGRAM is ENABLED"

trace "[loadConfig] Looking up TG_BOT_URL in database"
TG_BOT_URL=$(sql "SELECT value FROM cyphernode_props WHERE category='notifier' AND property='tg_base_url'")
returncode=$?
trace "[loadConfig] TG_BOT_URL [${TG_BOT_URL}]"
trace_rc ${returncode}
[ "${returncode}" -ne "0" ] && echo 10

trace "[loadConfig] Looking up TG_API_KEY in database"
TG_API_KEY=$(sql "SELECT value FROM cyphernode_props WHERE category='notifier' AND property='tg_api_key'")
returncode=$?
trace "[loadConfig] TG_API_KEY [${TG_API_KEY}]"
trace_rc ${returncode}
[ "${returncode}" -ne "0" ] && echo 20

trace "[loadConfig] Looking up TG_CHAT_ID in database"
TG_CHAT_ID=$(sql "SELECT value FROM cyphernode_props WHERE category='notifier' AND property='tg_chat_id'")
returncode=$?
trace "[loadConfig] TG_CHAT_ID [${TG_CHAT_ID}]"
trace_rc ${returncode}
[ "${returncode}" -ne "0" ] && echo 30
else
trace "[loadConfig] FEATURE_TELEGRAM is DISABLED"
fi

echo "0"
}


main
returncode=$?
trace "[requesthandler] exiting"
Expand Down
Loading