Как я могу использовать команду notify-send в сочетании с календарем Calcurse?

Я использую календарь и расписание приложения калькулятора. Это хорошая программа командной строки.

Например, с calcurse -a Вы можете отобразить события за день.

Как я могу отправить эту информацию notify-send, чтобы показать уведомление на рабочем столе?

$ calcurse -a | notify-send

не будет работать...

4 ответа

Решение

О калькуляторе

Как часто возвращение к (очень) базовой, но, тем не менее, полной функциональности кажется странным, но в некотором роде освежающим. Не уверен, если бы я использовал это все же.

Несмотря на то, что в нижней части окна Calcurse предлагается вариант передачи по трубопроводу, а на веб-сайте Calcurse упоминается " настраиваемая пользователем система уведомлений ", я не смог найти способ использовать ее для автоматических запланированных уведомлений обо всех событиях.

В то же время: действительно, такая функция напоминания была бы полезным дополнением. Сценарий ниже может быть использован в качестве плагина для calcurse показывать напоминания. Я надеюсь, что вы найдете это полезным.

Это чрезвычайно прост в использовании; просто запустите скрипт в фоновом режиме. Все, что он делает, это проверяет события на сегодня (обновляемые дважды в минуту) и запускает уведомления в произвольное время до истечения срока действия.

Что нужно для создания напоминаний

Вывод команды:

calcurse -a 

похоже:

12/29/15:
 * Free today!
 - 12:00 -> ..:..
    See if this script does its job :)

Сразу же происходит, что запланированные элементы начинаются с "-", а элементы на весь день начинаются с "*". Что нам нужно сделать, это создать две группы (списки) элементов:

  • запланированные
  • внеплановые

Что касается первой категории, нам нужно проанализировать время, преобразовать его в формат, с которым мы можем рассчитывать, чтобы мы могли показать напоминание в n - минут до истечения срока.

Впоследствии нам нужно "следить за часами", чтобы сравнить установленное время (события) с текущим временем. Если промежуток времени между ними входит в установленное время предупреждения, просто покажите уведомление.
Наконец, чтобы предотвратить повторное уведомление, нам нужно добавить элемент в "готовый" список.

Кроме того, скрипт очищает список "готово"; если элемент больше не встречается в сегодняшних элементах (либо если вы его удалили, либо день, перенесенный во время сеанса), элементы будут удалены автоматически.

Результат

При запуске (войти)

  • скрипт показывает все сегодняшние элементы подряд:

В произвольное время до истечения срока действия (в данном случае 15 минут)

  • сценарии напоминают вам в уведомлении:

Сценарий

#!/usr/bin/env python3
import subprocess
import time
import sys

warn = int(sys.argv[1])

def get(command):
    return subprocess.check_output(command).decode("utf-8")

def convert(t):
    # convert set time into a calculate- able time
    return [int(n) for n in t.split(":")]

def calc_diff(t_curr, t_event):
    # calculate time span
    diff_hr = (t_event[0] - t_curr[0])*60
    diff_m = t_event[1] - t_curr[1]
    return diff_hr + diff_m

def cleanup(done, newlist):
    # clean up "done" -lists
    for item in done:
        if not item in newlist:
            done.remove(item)
    return done

def show_time(event, s = ""):
    # show scheduled event
    hrs = str(event[0][0]); mnts = str(event[0][1])
    mnts = "0"+mnts if len(mnts) != 2 else mnts
    subprocess.call(["notify-send", s, "At "+hrs+":"+mnts+" - "+event[1]])

startups = []; times = []

while True:
    currtime = convert(time.strftime("%H:%M"))
    events = [l.strip() for l in get(["calcurse", "-a"]).splitlines()][1:]
    # arrange event data:
    groups = []; sub = []
    for l in events:
        if l.startswith("* "):
            groups.append([l.replace("* ", "")])
        elif l.startswith("- "):
            sub.append(convert(l.split("->")[0].replace("-", "").strip()))
        else:
            groups.append(sub+[l])
            sub = []
    # run notifications
    for item in groups:
        # on startup:
        if not item in startups:
            # all- day events
            if len(item) == 1:
                subprocess.call(["notify-send", "Today - "+item[0]])
            # time- specific events
            elif len(item) == 2:
                show_time(item, "Appointment")
            startups.append(item)
        # as a reminder:
        if all([len(item) == 2, not item in times]):
            span = calc_diff(currtime, item[0])
            if span <= warn:
                show_time(item, "[Reminder]")
                times.append(item)     
    # clean up events
    startups = cleanup(startups, groups); times = cleanup(times, groups)
    time.sleep(30)

Как пользоваться

  • Скопируйте скрипт в пустой файл, сохраните его как run_ccursereminders.py
  • Протестируйте его, указав в качестве аргумента время, за которое вы хотите получить предупреждение (до истечения срока действия, в минутах). Например, чтобы запустить напоминания за 30 минут до встречи:

    python3 /path/to/run_ccursereminders.py 30
    
  • Если это работает, как вы хотите, добавьте его в Startup Applications: выберите Dash > Startup Applications > Add. Добавьте команду

    /bin/bash -c "sleep 30 && python3 /path/to/run_ccursereminders.py 30"
    

    где последний 30 количество минут, чтобы предупредить вас до истечения срока встречи

Я смог заставить его работать с подстановкой команд:

notify-send "calcurse notification header" "$(calcurse -n)"

Я нет, это старый, но если кто-то все еще заинтересован, следующие настройки работают для меня в моем ~/.calcurse/conf файл:

notification.command=calcurse --next | xargs -0 notify-send "Appointment"
daemon.enable=yes
notification.warning=300

Я написал короткий скрипт bash , который будет использоваться в сочетании с для получения уведомлений. Он также поддерживает уведомления с переменными интервалами, а также уведомления о событиях в течение всего дня.

Это текущая версия скрипта:

      #!/bin/bash
#Will send a notification if the next appointment in the next 24 hours occurs within $1 minutes 
#Set $1 to be the time (minutes) you want the notification to pop up in advance before the appointment actually happens.
#This script should be executed by cron every minute or something like that thus it cannot run exactly $1 minutes before event. 
#So we use $2 to be the time +/- of $1 that it is okay to send the notification.
#Probably set $2 this to the same period between when cron runs this script

notify_within=$1
script_frequency=$2


#if there are no appointments in the next two days, the stop right away
if [ "$(calcurse -a -d 2)" = "" ] ; then
    exit 0
fi

if ! [ "$(calcurse -n)" = "" ] ; then #There is an event today with an associated time
    hours_remaining=$(calcurse -n | tail -1 | sed 's/ //g' | sed 's/\[//g' | sed 's/\].*//g' | sed 's/:..//g')
    minutes_remaining=$(calcurse -n | tail -1 | sed 's/ //g' | sed 's/\[//g' | sed 's/\].*//g' | sed 's/..://g')
    
    
    time_remaining=$( echo "$hours_remaining * 60 + $minutes_remaining" | bc ) #in minutes. just adding the hours to minutes
    
    #Test whether the next event is within the given time frame
    #We need bc (calculator) to do the calculation. Will return "1" if the conditional is true
    #0.95 factor because you can get notifications to pop 3 times if cron is running every 1 minute and you use script_frequency=1
    notify_boolean=$( echo "$time_remaining <= ($script_frequency*0.95 + $notify_within) && $time_remaining >= ($notify_within - $script_frequency*0.95)" | bc )
    if [ "$notify_boolean" = 1 ] ; then
        eventname="$(calcurse -n | sed -n 2p | sed 's/^   \[..:..\] //g')"
        event_in="$(calcurse -n | sed -n 2p | sed 's/^   \[//g' | sed 's/\].*//g')"
        notify-send "Appointment: ${eventname} in ${event_in}"
        fbcli -t -1 -E message-new-instant 2>&1 >/dev/null || true #send a request to vibrate and make sound with feedbackd if possible
    fi
fi

tomorrow="$(date --date 'next day' +"%Y-%m-%d")"
daily_events="$(calcurse -a -d 2 | tr "\n" "@" | sed "0,/^.*${tomorrow}/ s///" | sed 's/^:@ \* //g' | sed 's/@ \* /, /g' | sed 's/@$//g' )" #Gives list of daily events tomorrow, Hopefully your event doesn't have "@" in it
if ! [ "$daily_events" = "" ] ; then 
    current_hour="$(date +"%H")"
    current_minute="$(date +"%H")"
    minutes_today=$(( $current_hour * 60 + $current_minute )) #Minutes that have elapsed today
    minutes_left_today=$(( 24*60 - $minutes_today )) #Minutes elapsed at midnight
    notify_boolean_2="$(echo "$minutes_left_today <= ($script_frequency*0.95 + $notify_within)" | bc )" #It is $notify_within minutes of midnight!
    if [ "$notify_boolean_2" = 1 ] ; then
        notify-send "Daily Events: $daily_events"
        fbcli -t -1 -E message-new-instant 2>&1 >/dev/null || true #send a request to vibrate and make sound with feedbackd if possible
    fi
fi

И это cronстрока для вызова:

      */2 * * * * export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus; /path/to/calendar_appointment_notify.sh 30 2

Этот сценарий зависит от

  • libnotify
  • накипь
  • до н.э
  • свидание

Разумеется, актуальную версию можно найти на GitHUB.

Другие вопросы по тегам