iris-search/iris-search

370 lines
8.9 KiB
Bash
Executable File

#! /bin/bash
localdir=~/.local/share/iris
[[ -d $localdir/.fultmod ]] || mkdir -p $localdir
[[ -f $localdir/.fultmod ]] || touch -d '2000-01-01' $localdir/.fultmod
# fultmod: fecha y hora desde la que hay que cargar nuevos mensajes
fultmod=$localdir/.fultmod
fultmod2=$localdir/.fultmod2
mensajes=$localdir/mensajes.txt
leidos=$localdir/leidos.txt
bd=$localdir/iris.sqlite
function update {
# Actualizar la base de datos
echo "Updating database..." >&2
# .fultmod2: fecha y hora de esta actualización
touch $fultmod2
# Obtener la lista de mensajes y guardarla en $mensajes
echo "hash|edit_hash|is_deleted|author|parent|timestamp|message" > $mensajes
find /home/*/.iris.messages -newer $fultmod | while read mensajes; do
jq '.[] | .hash + "|" + .edit_hash + "|" + ( .is_deleted | tostring ) + "|" + .data.author + "|" + .data.parent + "|" + .data.timestamp + "|" + (.data.message | gsub("\\|"; ":pipe:"))' "$mensajes"
done | tr -d '"' >> $mensajes
# Obtener la lista de mensajes leídos y guardarla en leidos
echo "hash" > $leidos
jq '.[]' ~/.iris.messages.read | tr -d '"' >> $leidos
# Guardar la información en sqlite
sqlite3 $bd <<< "
CREATE TABLE IF NOT EXISTS 'mensajes'(
'hash' TEXT,
'edit_hash' TEXT,
'is_deleted' TEXT,
'author' TEXT,
'parent' TEXT,
'timestamp' TEXT,
'message' TEXT
);
CREATE TABLE IF NOT EXISTS 'leidos'(
'hash' TEXT
);
CREATE INDEX IF NOT EXISTS mensajes_idx_00014b4c ON mensajes(hash);
CREATE INDEX IF NOT EXISTS leidos_idx_00014b4c ON leidos(hash);
.import $mensajes mensajes
.import $leidos leidos
create temporary table duplicados as
select rowid as id
from mensajes a
where exists
(
select 1
from mensajes b
where b.hash = a.hash
and b.rowid < a.rowid
);
delete from mensajes where rowid in (select id from duplicados);
delete from mensajes where timestamp = 'timestamp';
drop table duplicados;
create temporary table duplicados as
select rowid as id
from leidos a
where exists
(
select 1
from leidos b
where b.hash = a.hash
and b.rowid < a.rowid
);
delete from leidos where rowid in (select id from duplicados);
" && {
mv $fultmod2 $fultmod
rm $mensajes $leidos
}
}
function ls_all {
# Listar todos los hilos
sqlite3 $bd <<< "
select distinct
rowid
, substr(timestamp,1,10)
, substr(author,1,instr(author, '@')-1)
, case when instr(message, '\n') > 0
then substr(message,1,instr(message, '\n')-1)
else message
end as message
from mensajes
where
is_deleted <> 'true'
and parent = ''
and edit_hash = ''
order by timestamp desc"
}
function search {
# Buscar hilos por palabras mencionadas en los mensajes
sqlite3 $bd <<< "
select distinct
rowid
, substr(timestamp,1,10)
, substr(author,1,instr(author, '@')-1)
, case when instr(message, '\n') > 0
then substr(message,1,instr(message, '\n')-1)
else message
end as message
from mensajes
where
(
is_deleted <> 'true'
and parent = ''
and edit_hash = ''
and message like '%$1%'
) or (
hash = (
select parent
from mensajes
where
is_deleted <> 'true'
and parent <> ''
and edit_hash = ''
and message like '%$1%'
)
)
order by timestamp desc"
}
function ls_unread {
# Listar hilos con mensajes sin leer
sqlite3 $bd <<< "
select distinct
rowid
, substr(timestamp,1,10)
, substr(author,1,instr(author, '@')-1)
, case when instr(message, '\n') > 0
then substr(message,1,instr(message, '\n')-1)
else message
end as message
from mensajes a
where
is_deleted <> 'true'
and parent = ''
and edit_hash = ''
and (
hash not in (
select hash from leidos
)
or
exists (
select 1
from mensajes b
where parent = a.hash
and b.hash not in (
select hash from leidos
)
)
)
order by timestamp desc"
}
function t {
# Menú para elegir un hilo de la lista completa
while : ; do
update
mensaje="$(ls_all | menu "Filter: (Esc to go back) ")"
[[ -z $mensaje ]] && break
show $mensaje
done
unset mensaje
}
function u {
# Menú para elegir un hilo entre los que tienen mensajes sin leer
while : ; do
update
[[ $(ls_unread | wc -l) -gt 0 ]] ||
{
echo "All messages read. Press any key to continue" >&2
read -sn1
break
}
mensaje="$(ls_unread | menu "Filter: (Esc to go back) ")" &&
[[ -z $mensaje ]] && break
show $mensaje
done
unset mensaje
}
function s {
# Buscar un hilo por palabras
update
lista="$(search "$1")"
[[ -z "$lista" ]] &&
{
echo "\"$1\" not found. Press any key to continue" >&2
read -sn1
return
}
unset mensaje
mensaje="$(search "$1" | menu)" &&
[[ -n $mensaje ]] && show $mensaje
unset mensaje
}
function menu {
column -t -s'|' |
fzf -e --reverse --no-sort --info=hidden --prompt="$1" |
cut -d' ' -f1
}
function thread {
# Obtener el hash del mensaje inicial del hilo
hash=$(sqlite3 $bd <<< "
select hash
from mensajes
where rowid = '$1'")
{
sqlite3 $bd <<< "
select
substr(timestamp,1,10),
author,
message
from mensajes
where rowid = '$1'"
sqlite3 $bd <<< "
select
substr(timestamp,1,10),
author,
message
from mensajes
where
is_deleted <> 'true'
and parent = '$hash'
and edit_hash = ''
order by timestamp"
} |
sed 's/\\n/:nl:/g'
}
function show {
# Mostrar los mensajes de un hilo
# Obtener el hash del mensaje inicial del hilo
hash=$(sqlite3 $bd <<< "
select hash
from mensajes
where rowid = '$1'")
# Obtener la anchura del terminal
anchura=$(tput cols)
margen=0
[[ $anchura -gt 80 ]] &&
margen=$(( ($anchura - 80)/2 )) &&
anchura=80 &&
[[ $margen -gt 3 ]] &&
margen=3
# Mostrar los mensajes del hilo
clear
{
echo "<<< Press q to go back"
thread "$1" |
while IFS='|' read fecha autor mensaje; do
echo;
echo -e "\033[0;32m$fecha $autor\033[0m";
echo "$mensaje" |
sed 's/:nl:/\n/g; s/:pipe:/|/g' |
fold -s -w $anchura;
done |
awk -v margen=$margen '{for (i=0; i<margen; i++){printf " "}; print $0}'
} | less -r
# Marcar mensajes como leídos
sqlite3 $bd <<< "
insert into leidos
select hash
from mensajes
where rowid = '$1'
and hash not in (select hash from leidos)
union
select hash
from mensajes
where parent = '$hash'
and hash not in (select hash from leidos);"
sqlite3 $bd <<< "select distinct hash from leidos order by hash" |
awk '
BEGIN {
printf "["
}
{
if (NR>1){
sep=","
}
}
{
printf sep "\"" $1 "\"";
}
END {
print "]"
}
' > "$HOME/.iris.messages.read"
}
# Show TUI only if first parameter is null
# Useful for source the functions:
# . path/to/iris-search silent
[[ -z $1 ]] && while true; do
clear
res="$(echo "1 Unread
2 All topics
3 Search
4 Quit" | menu "Iris forum: " | cut -d' ' -f1)"
[[ -z $res ]] && break
case $res in
1)
u
;;
2)
t
;;
3)
clear
read -p "Search word: " word
s "$word"
;;
4)
break
;;
*)
:
;;
esac
done &&
clear