You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

475 lines
18 KiB

#!/bin/bash
########################################################################
# Author: Fred (support@qo-op.com)
# Version: 2020.03.18
# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
########################################################################
MY_PATH="`dirname \"$0\"`" # relative
MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized
ME="${0##*/}"
echo '
########################################################################
# \\///
# qo-op
############# '$ME' creates ZenTag (+ Passenger)'
ZEN="$1" # Zen amount
ZENSOURCE="$2" # G1 TX HASH OR PASSENGER timestamp ~/.zen/miam/timestamp/
PASSENGER="$3" # ~/.zen/miam/timestamp/src_id.ext in ZenTag (add to IPFS datastructure)
METADATA="$4"
READ="$5" # Zen amount asked to allow passenger reading
PARK="$6" # Zen amount payed for IPFS PIN by passenger everyday
# Add any "parameters" needed by CONTRACT.sh
echo "
########################################################################
# $MY_PATH/$ME $ZEN $ZENSOURCE $PASSENGER $READ $PARK $METADATA
# IPFS DATASTRUCTURE ~/.zen/tag/sha256sum(_tag.uid)
########################################################################
# [ASTROPORT](https://astroport.com)
########################################################################"
# If PASSENGER file, then must provide METADATA!
[[ $PASSENGER != "" ]] && [[ $METADATA == "" ]] && echo "ERROR PASSENGER needs METADATA !!! Please verify and correct..." && exit 1
[[ $READ == "" ]] && READ=1
[[ $PARK == "" ]] && PARK=10
##############################################
# NODE ENVIRONEMENT DETECTION
##############################################
IPFSNODEID=$(ipfs id -f='<id>\n')
[[ ! -f ~/.ssb/secret.dunikey ]] && $MY_PATH/tools/secret2dunikey.sh
G1PUB=$(cat ~/.ssb/secret.dunikey | grep 'pub:' | cut -d ' ' -f 2)
echo "G1SSB Wallet: $G1PUB
IPFS: $IPFSNODEID
__ __ _ _ _______
_______ _ __ | \/ | / \ | |/ / ____|
|_ / _ \ '_ \ | |\/| | / _ \ | ' /| _|
/ / __/ | | | | | | |/ ___ \| . \| |___
/___\___|_| |_| |_| |_/_/ \_\_|\_\_____|
"
########################################################################
# ZenTag is an IPFS/IPNS datastructure shared into IPFS, publish
# ~~~ Draft ~~~~ Draft ~~~~ Draft ~~~~ Draft ~~~~ Draft ~~~~
# _chain # ZenTag IPFS Hash
# _chain.n # Sequence Number
# _chain.nanodate # Current nanodate
# _chain.prev # Previous IPFS Hash
# _g1.node.creator # G1SSB wallet pubkey
# _tag.issuer # G1TX ISSUER pubkey
# _tag.zensource # G1TX HASH or SSB timestamp
# _ipfs.node.creatorcat # NODE IPFS ID
# _ipfs.publishkey.BB.aes # BB SYMcypher of IPNS publish key
# _ipfs.publishkey.crypt # G1SSB ASYMcypher of IPNS publish key
# _tag.BB.sha # BB sha256sum
# _tag.uid # ZenTag UID
# _tag.zen # ZentTag balance
# _ipns # /ipns/ address
# PASSENGER FILE (put to IPFS and cypher link in IPNS ZenTag)
# _passenger.filename # Passenger filename
# _passenger.ipfs.crypt # G1SSB cyphered IPFS Passenger link
# _passenger.read # Zen value asked for READING
# _passenger.park # Zen value paid for PARKING
# Only if contract executed => add new cyphered links
# _passenger.contract.sh # Zen CONTRACT TODO
# COmpare with code to verify and extend Draft
# TODO: Could be converted into yaml or json if you like...
########################################################################
#TAG IS MANAGED BY NODE KEY OR BB KEY to change IPNS latest status
#INDEX UPDATE ON CURRENT NODE IPFS SWARM CHANNEL
[[ $ZEN == "" || $ZENSOURCE == "" ]] && echo "ERROR... Please provide Zen value" && exit 1
if [[ "$METADATA" == "" ]]; then
echo "
# LOVE BANK - PrePaid Card ZenTag
# FULLY BACKED ON IRL G1 LIBRE MONEY (https://cesium.app)
# ____ ____ _____ _____ _ _
# / ___| _ \| ____| ____| \ | | _______ _ __
# | | _| |_) | _| | _| | \| | |_ / _ \ '_ \
# | |_| | _ <| |___| |___| |\ | / / __/ | | |
# \____|_| \_\_____|_____|_| \_| /___\___|_| |_|
#
"
# COMMENT WILL BREAK (G1 <=> ZEN) STRICT RELATION
[[ ! -f ~/.zen/cache/g1_TX_inputs/zen.$ZENSOURCE ]] && echo "ERROR# UNKNOWN ~/.zen/cache/g1_TX_inputs/zen.$ZENSOURCE !!" && exit 1
ISSUER=$(cat ~/.zen/cache/g1_TX_inputs/zen.$ZENSOURCE)
[[ $ISSUER == "" ]] && echo "ERROR# NO ISSUER FOUND FOR TX $ZENSOURCE !!" && exit 1
echo "ISSUER = $ISSUER SENT TX $ZENSOURCE !!"
else
echo "
_|_ o ._ _ _ _ _|_ _. ._ _ ._
|_ | | | | (/_ _> |_ (_| | | | |_)
|
SSB PASSENGER ~/.zen/miam/$ZENSOURCE
"
[[ ! -d ~/.zen/miam/$ZENSOURCE ]] && echo "ERROR# UNKNOWN ~/.zen/miam/$ZENSOURCE !!" && exit 1
ISSUER=$(cat ~/.zen/miam/$ZENSOURCE/msg_key)
[[ $ISSUER == "" ]] && echo "ERROR# NO ISSUER FOUND FOR miam $ZENSOURCE !!" && exit 1
echo "ISSUER = SSB Message $ISSUER !!"
fi
########################################################################
# CREATE ZEN TAG
########################################################################
# Produce unique 6 words diceware to give a name _tag.uid
AA=$(echo $($MY_PATH/tools/diceware.sh 6 | xargs) | sed s/\ /_/g ) # ZenTag Name = Diceware_6_words
AAH=$(echo -n ${AA} | sha256sum | cut -d ' ' -f 1) # ZenTag Name SHA256
# TODO ACTIVATE SWARM UNICITY CHECK
# Create Unique Zentag for all IPFS SWARM!
while [[ $(grep -Rwl "$AA" ~/.zen/ipfs_swarm/.12D3KooW*/TAG/*/_tag.uid) ]]; do
AA=$(echo $($MY_PATH/tools/diceware.sh 6 | xargs) | sed s/\ /_/g )
AAH=$(echo -n ${AA} | sha256sum | cut -d ' ' -f 1)
done
# BB key is a 4 word diceware printed on QRCode for Human use.
# SHA256 PASSWORD CHECK FOR ALLOWING WRITE ACTION
BB=$($MY_PATH/tools/diceware.sh 4 | xargs);
BBH=$(echo -n "$BB" | sha256sum | cut -d ' ' -f 1)
########################################################################
# INITIAL DATA STRUCTURE
########################################################################
mkdir -p ~/.zen/tag/${AAH}
# LOG
echo "
_____ _____ _ ____
|__ /___ _ _|_ _|/ \ / ___| __/\__
/ // _ \ °_ \| | / _ \| | _ \ /
/ /| __/ | | | |/ ___ \ |_| | /_ _\
/____\___|_| |_|_/_/ \_\____| \/
*******************************************************
| $AA | $ZEN Zen
*******************************************************
CREATING ~/.zen/tag/${AAH}/
"
# COPY ZENTAG TO LOCAL ~/.zen/tag
echo "$AA" > ~/.zen/tag/${AAH}/_tag.uid # Nom du ZenTAG
echo "$ZEN" > ~/.zen/tag/${AAH}/_tag.zen # Tag ZEN amount
echo "${IPFSNODEID}" > ~/.zen/tag/${AAH}/_ipfs.node.creator # NODE IPFS ID
echo "$ZENSOURCE" > ~/.zen/tag/${AAH}/_tag.zensource # ZENSOURCE
echo "$G1PUB" > ~/.zen/tag/${AAH}/_g1.node.creator # CREATOR IPFS NODE G1PUBKEY
echo "$ISSUER" > ~/.zen/tag/${AAH}/_tag.issuer # TX ISSUER G1PUBKEY OR SSB_MESSAGE ID
########################################################################
# Create IPNS publishing key ${AA}.key
# =====================================
# BB encrypted version for IRL use
# G1PUB for current G1SSB Node later access...
# Using sha256sum / openssl / natools.py (libsodium)
########################################################################
#timestamp=$(date -u +%s%N | cut -b1-13)
keyname="${ZENSOURCE}_${AA}.key"
[[ ! $(ipfs key list | grep -F ${AA}.key) ]] && J0=$(ipfs key gen -t rsa -s 2048 $keyname)
# WRITE BBH for QRCode BB verification
echo "$BBH" > ~/.zen/tag/${AAH}/_tag.BB.sha
# BB pgp symetric publishkey
keyfilename=$(ls ~/.ipfs/keystore/ | tail -n 1)
openssl aes-256-cbc -pbkdf2 -k "$BB" -salt -in ~/.ipfs/keystore/${keyfilename} -out ~/.zen/tag/${AAH}/_ipfs.publishkey.BB.aes
# GIVE IPFS CREATOR NODE ACCESS TO ZEN TAG
$MY_PATH/tools/natools.py encrypt -p $G1PUB -i ~/.ipfs/keystore/${keyfilename} -o ~/.zen/tag/${AAH}/_ipfs.publishkey.crypt
# LOG
echo "
${AA}.key
CYPHERING PUBLISH KEY
__ _
_/_/ __/|_ __/|_ | |
/ / | / | / / /
/ / /_ __| /_ __| / /
/ / |/ |/ _/_/
|_| /_/
KEY : $BB
BBH : $BBH
"
#######################################################################
# PASSENGER FILE is added to IPFS (then link is cyphered: NO!)
# https://beechat.network/how-beechats-encryption-works/
# SECURITY IS OBSOLETE AS WE ARE SHARING COPY WITH FRIENDS ;)
# ACTIVATE ZEN CONTRACT... 100 readers impresari
# LOVE ECONOMY IS FREE. EVERYBODY IS DONATING TO THE OTHERS NOW.
# INCOME != MONEY FORGE (Realtive Moey Theory applies HERE)
# CODE WILL BE CERTIFIED AS IPFS HASH.
if [[ -f $PASSENGER ]]; then
echo "
_ _ _ _ _ _ _ _ _
/ \ / \ / \ / \ / \ / \ / \ / \ / \
( p | a | s | s | e | n | g | e | r )
\_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
"
# SEARCH FOR SAME SOURCE in IPFS... Not to make it twice...
CHECKSWARM=$(grep -Rwl "$ZENSOURCE" ~/.zen/ipfs_swarm/.12D3KooW*/TAG/*/_tag.zensource | tail -n 1 | cut -f 6 -d '/')
[[ $CHECKSWARM == "" ]] && CHECKSWARM=$(grep -Rwl "$ZENSOURCE" ~/.zen/ipfs/.$IPFSNODEID/TAG/*/_tag.zensource | tail -n 1 | cut -f 6 -d '/')
[[ -s ~/.zen/ipfs/.$IPFSNODEID/TAG/$ZENSOURCE/_tag.issuer ]] && ISSUERSWARM=$(cat ~/.zen/ipfs/.$IPFSNODEID/TAG/$ZENSOURCE/_tag.issuer)
[[ "$CHECKSWARM" != "" && "$ISSUERSWARM" == "$ISSUER" ]] && ipfs key rm $keyname && rm -Rf ~/.zen/tag/${AAH} \
&& echo "$ZENSOURCE ALREADY COPIED IN IPFS SWARM. $CHECKSWARM CANCEL" && exit 1
# NO DUPLICATE
echo "ADDING TO IPFS.................$(date)"
# ADD PASSENGER TO IPFS # COULD BE SUPER LONG !!!
IPASSENGER=$(ipfs add -q "$PASSENGER" -w | tail -n 1)
# TODO COMPARE DISK WRITING SPEED AND AVAILABLE SPACE TO CHOOSE BEST IN SWARM
echo "$(date) ............... YES /ipfs/$IPASSENGER"
echo "$IPASSENGER" > ~/.zen/tag/${AAH}/_passenger.ipfs
# GET FILE NAME
PASSENGERNAME=$(basename -- "$PASSENGER")
echo "$PASSENGERNAME" > ~/.zen/tag/${AAH}/_passenger.filename
# G1SSB NODE ACCESS
$MY_PATH/tools/natools.py encrypt -p $G1PUB -i ~/.zen/tag/${AAH}/_passenger.ipfs -o ~/.zen/tag/${AAH}/_passenger.ipfs.crypt
# BB OWNER ACCESS
openssl aes-256-cbc -pbkdf2 -k "$BB" -salt -in ~/.zen/tag/${AAH}/_passenger.ipfs -out ~/.zen/tag/${AAH}/_passenger.ipfs.BB.aes
# CLEAN CLEARTEXT IPFS link ? LATER MAYBE
rm ~/.zen/tag/${AAH}/_passenger.ipfs
# ZEN ECONOMY: ZEN READ payment + PARK rental
echo "$READ" > ~/.zen/tag/${AAH}/_passenger.read
echo "$PARK" > ~/.zen/tag/${AAH}/_passenger.park
echo "
_passenger.filename : $PASSENGERNAME
_passenger.ipfs : $IPASSENGER
http://127.0.0.1:8080/ipfs/$IPASSENGER/$PASSENGERNAME
# #### ## ##### ###### #####
# # # # # # # # # #
# # # # # # # ##### # #
# # # ###### # # # # #
# # # # # # # # # #
###### #### # # ##### ###### #####
##################################################################
# DECODE AND READ _passenger.ipfs with BB Passphrase
##################################################################
openssl aes-256-cbc -pbkdf2 -k \"$BB\" -d -salt -in ~/.zen/tag/${AAH}/_passenger.ipfs.BB.aes -out /tmp/_passenger.ipfs
ipfs get -o /tmp \"/ipfs/$IPASSENGER/$PASSENGERNAME\" && vlc \"/tmp/$PASSENGERNAME\" 2>/dev/null
"
cat > ~/.zen/tag/${AAH}/CONTRACT.sh <<EOF
#!/bin/bash
# Version 0.0
{
echo
'# THIS CODE INITIATE A CONTRACT
# Established by/with _ipfs.node.creator
# Gives Access SSB friend + IPFS Swarm allowance to read ipfs link
#In order io get access file : $PASSENGERNAME
#You must execute that code.
# ..... TODO ......
# It is bash or javascript or python
# or any language code with connection with g1, ipfs or ssb
# or Send $READ Zen to $G1PUB with $PASSENGERNAME in comment
# .... TODO ....
# Once contract is validated
# NodeN will be able to decrypt _passenger.ipfs.NodeN.crypt'
exit 0
}
EOF
fi
# END PASSENGER FILE
####################
###########################################################
# Copy TAG into IPFS + ipfs name publish -k ${AA}.key
###########################################################
# ZenTAG CHAIN
echo "0" > ~/.zen/tag/${AAH}/_chain.n # Tag modification number (0 first)
NANODATE=$(date -u +%s%N)
echo "$NANODATE" > ~/.zen/tag/${AAH}/_chain.nanodate # Nanodate notification
I0=$(ipfs add -qr ~/.zen/tag/${AAH} | tail -n 1)
echo "${I0}" > ~/.zen/tag/${AAH}/_chain
# Double IPFS add for _chain INIT
cp -f ~/.zen/tag/${AAH}/_chain ~/.zen/tag/${AAH}/_chain.prev
I=$(ipfs add -qr ~/.zen/tag/${AAH} | tail -n 1)
echo "${I}" > ~/.zen/tag/${AAH}/_chain
echo "
_|_ _.o._
(_| |(_||| | : $NANODATE
J0=${J0}
I0=${I0}
I=${I}
"
# IPNS name publish
J=$(ipfs name publish -k $keyname --quieter /ipfs/${I})
[[ ! ${J} ]] && echo "ipfs pin rm ${I}; ipfs pin rm ${I0}; rm -Rf ~/.zen/tag/${AAH}; ipfs key rm $keyname "
[[ ! ${J} ]] && J=${J0}
echo "${J}" > ~/.zen/tag/${AAH}/_ipns
# INDEXING ZenTag into SWARM
mkdir -p ~/.zen/ipfs/.$IPFSNODEID/TAG/${ZENSOURCE}/
echo "${AA}" > ~/.zen/ipfs/.$IPFSNODEID/TAG/${ZENSOURCE}/_tag.uid
echo "${ZENSOURCE}" > ~/.zen/ipfs/.$IPFSNODEID/TAG/${ZENSOURCE}/_tag.zensource
echo "${ISSUER}" > ~/.zen/ipfs/.$IPFSNODEID/TAG/${ZENSOURCE}/_tag.issuer
echo "${J}" > ~/.zen/ipfs/.$IPFSNODEID/TAG/${ZENSOURCE}/_tag.ipns
if [[ "${PASSENGERNAME}" != "" ]]; then
echo "${PASSENGERNAME}" > ~/.zen/ipfs/.$IPFSNODEID/TAG/${ZENSOURCE}/_tag.passenger.filename
# COPY METADATA!! TODO : Please Extend filesource FOR new metadata types. torrent ?
extractor=$(cat "$METADATA" | jq -r '.extractor')
youtubeid=$(cat "$METADATA" | jq -r '.id')
fulltitle=$(cat "$METADATA" | jq -r '.fulltitle')
echo "$fulltitle" > ~/.zen/ipfs/.$IPFSNODEID/TAG/${ZENSOURCE}/_tag.passenger.fulltitle
# description=$(cat "$METADATA" | jq -r '.description')
artist=$(cat "$METADATA" | jq -r '.artist')
album=$(cat "$METADATA" | jq -r '.album')
duration=$(cat "$METADATA" | jq -r '.duration')
upload_date=$(cat "$METADATA" | jq -r '.upload_date')
uploader_id=$(cat "$METADATA" | jq -r '.uploader_id')
extractor=$(cat "$METADATA" | jq -r '.extractor')
[[ ! -f ~/.zen/ipfs/.$IPFSNODEID/TAG/${ZENSOURCE}/_tag.passenger.metadata.${extractor}.json ]] \
&& cp -f "${METADATA}" /tmp/
mv /tmp/${youtubeid}.info.json ~/.zen/ipfs/.$IPFSNODEID/TAG/${ZENSOURCE}/_tag.passenger.metadata.${extractor}.json
fi
ls ~/.zen/ipfs/.$IPFSNODEID/TAG/${ZENSOURCE}/
IWALLETS=$(ipfs add -rHq ~/.zen/ipfs | tail -n 1)
NODEIPNS=$(ipfs name publish --quieter /ipfs/$IWALLETS)
echo "
_ ____
(_)___ / __/____
/ / __ \/ /_/ ___/
/ / /_/ / __(__ )
/_/ .___/_/ /____/
/_/
ipfs ls /ipfs/${I}
ZenTAG : ipfs ls /ipns/${J}
NODE index : ipfs ls /ipns/$IPFSNODEID/.$IPFSNODEID/TAG/${ZENSOURCE}
"
########################################################################
# CREATE ZenTAG READ/WRITE QRCODES
### PRINTER IS HOOKED TO G1SSB NODE = G1DAB
########################################################################
echo "
_ _ _ _ _ _
/ \|_) / / \| \|_
\_X| \ \_\_/|_/|_ .................................
"
# READ QRCODE
qrencode -s 5 -o ~/.zen/tag/${AAH}/_QRCODE.read.png "RJ:${AA}#${J}"
# WRITE QRCODE
qrencode -s 5 -o ~/.zen/tag/${AAH}/_QRCODE.write.png "BJ:${BB}#${J}"
## TODO PROD REMOVE WRITE FILE
echo "QRCodes CREATED !!
See it :
xviewer ~/.zen/tag/${AAH}/_QRCODE.read.png &
xviewer ~/.zen/tag/${AAH}/_QRCODE.write.png &
${AA}
"
[[ $(which xviewer) ]] && xviewer ~/.zen/tag/${AAH}/_QRCODE.read.png &
[[ $(which xviewer) ]] && xviewer ~/.zen/tag/${AAH}/_QRCODE.write.png &
########################################################################
# SBOT PUBLISH
########################################################################
if [[ "${PASSENGERNAME}" != "" ]]; then
echo "$ISSUER"
msg="$(sbotc get '{"id":"'"$ISSUER"'"}')"
# echo "$msg" | jq #DEBUG
[[ $msg == "" ]] && echo "ERROR No SSB message for PASSENGER (timestamp: $tstamp)" && exit 1
msg_root=$(printf %s "$msg" | jq -r .value.content.root)
[[ $msg_root == "null" ]] && msg_root=$ISSUER
msg_branch=$(printf %s "$msg" | jq -r .value.content.branch)
[[ $msg_branch == "null" ]] && msg_branch=$ISSUER
# ATTACH ~/.zen/miam/$ZENSOURCE/ssb_thumb.jpg
name="ssb_thumb.jpg"
id="$(sbotc blobs.add < ~/.zen/miam/$ZENSOURCE/ssb_thumb.jpg)"
type="$(file -b --mime-type ~/.zen/miam/$ZENSOURCE/ssb_thumb.jpg)"
size="$(wc -c < ~/.zen/miam/$ZENSOURCE/ssb_thumb.jpg)"
export MESSAGE=$(cat << EOF
[![ssb_thumb.jpg](${id})](http://127.0.0.1:8080/ipfs/$IPASSENGER/$PASSENGERNAME)
:extractor:${extractor}
:fulltitle:${fulltitle}
:duration:${duration}
:uploader_id:${uploader_id}
[:pig:IPFS:pig_nose:](http://127.0.0.1:8080/ipfs/$IPASSENGER/$PASSENGERNAME)
---
**ZEN=$ZEN($READ/$PARK)**
[:flying_saucer:Essaim IPFS:sparkle:](http://127.0.0.1:8080/ipns/${J}/CONTRACT.sh)
[:sunglasses:**ZenTAG**:heart:DEBUG:pager:](http://127.0.0.1:8080/ipns/$IPFSNODEID/.$IPFSNODEID/TAG/${ZENSOURCE})
#zenbot
#astroport
EOF
)
echo "
__ _ ____
(_ |_)/ \|
__)|_)\_/| POST
root: $msg_root
branch: $msg_branch
"
echo "$MESSAGE"
INLINE=$(node -p "JSON.stringify(process.env.MESSAGE)")
### TODO find sboyc text COMMA PROBLEM... Cannot send beautiful md formated SSB messages !!!
# echo '{"type":"post", "branch": "'"$msg_branch"'", "root": "'"$msg_root"'", "text":"'"${INLINE}"'","mentions":[{"link":"'"$id"'","name":"'"$name"'","size":"'"$size"'","type":"'"$type"'"},{"link":"#zenbot"},{"link":"#astroport"}]}'
sbotc publish '{"type":"post", "branch": "'"$msg_branch"'", "root": "'"$msg_root"'", "text":'${INLINE}',"mentions":[{"link":"'"$id"'","name":"'"$name"'","size":"'"$size"'","type":"'"$type"'"},{"link":"#zenbot"},{"link":"#astroport"}]}'
else
# This code is activated for qrcode (zentx terminal) @piniche
# REGULAR ZenTAG, Send QRCode to INPUT TX emitter
### TODO PRINT AND SEND BY SSB WITH WHEN PASSENGER TOO
# CAREFULL IN THAT CASE ISSUER IS A G1WALLET
ssbid="@$(echo $ISSUER | base58 -d | base64).ed25519"
file=~/.zen/tag/${AAH}/_QRCODE.read.png
#recps='@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519 @5XaVcAJ5DklwuuIkjGz4lwm2rOnMHHovhNg7BFFnyJ8=.ed25519'
recps="$ssbid"
name=${file##*/}
link="$(sblob encrypt "$file")"
type="$(file -b --mime-type "$file")"
id=${link%?unbox=*}
key=${link#*?unbox=}
size="$(sbotc -e blobs.size "$id")"
recps_array="[$(for recp in $recps; do printf '"%s"\n' "$recp"; done | paste -sd,)]"
sbotc private.publish '{"type":"post","text":"['"$name"']('"$link"')","mentions":[{"link":"'"$id"'","name":"'"$name"'","size":'"$size"',"type":"'"$type"'","query":{"unbox":"'"$key"'"}}],"recps":'"$recps_array"'}' "$recps_array"
fi
########################################################################
exit 0