You are not logged in.
I'm a bit of an odd duck and I use Rob Pike's acme as my text editor/general programming environment. Recently, I wrote an RSS feed for it by converting all the RSS feeds to JSON feeds and using the following to display a summary of my subscriptions:
#!/bin/sh
# RSS/Atom/JSON Feed reader for acme
# This code is in the public domain
for url in $(cat $URLS)
do
temp=$(mktemp)
curl -s $url > $temp
jq -r '.title' $temp
echo
jq -r ' .items | .[] | [.title, .url] | join("\t") ' $temp | head -n 5
echo
echo =====
echo
rm $temp
done | 9p write acme/new/body
writetoacme JSON-Feeds
"writetoacme" is also a script I wrote to help with writing acme screens.
#!/bin/sh
# Shortcut for common writing acme applications
# USAGE: writetoacme $1
# $1: name of window
last=$(9p ls acme | sort -g | tail -n 1)
echo "name $1" | 9p write acme/$last/ctl
echo -n "clean" | 9p write acme/$last/ctl
echo -n "0,0" | 9p write acme/$last/addr
echo -n "dot=addr" | 9p write acme/$last/ctl
echo -n "show" | 9p write acme/$last/ctl
EDIT: before anyone asks, I simply use a web-service called feed2json to do all the converting for me. I'll probably write my own program to do that later on. But this works for now.
Last edited by pellertson (2019-05-19 05:31:47)
Offline
for url in $(cat $URLS)
do
# ...
done
Save the cats!
while read url
do
# ...
done < $URLS
You also may be interested in python's feedparser which would drastically simplify the whole process.
Last edited by Trilby (2019-05-19 12:21:35)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Online
Props for the acme rss script, pellertson! You've inspired me to finish putting together my own version (sans the Web service), something I've been meaning to do for a while.
Offline
You also may be interested in python's feedparser which would drastically simplify the whole process.
That could be useful, but I've found through experience that shell scripts are truly the best way to write to acme screens. As readable as python is, I cannot go without pipes. Plus I wanted to learn how to use "jq". But thanks for the tip on removing cat!
Offline
Props for the acme rss script, pellertson! You've inspired me to finish putting together my own version (sans the Web service), something I've been meaning to do for a while.
Thanks! Can I see your version?
Offline
I was looking to watch websites for changes, but all I found was a paid service. So I decided to host my own solution.
The script is run from cron, and supports three methods of comparison:
1. direct HTML comparison (using curl). This may result in false positives, especially with javascript-heavy sites.
2. text rendering (using w3m). This does not necessarily render all content (again, javascript).
3. full rendering (using cutycapt/qtwebengine). Heavy-handed but reliable approach for most websites. An image overlay is sent as email attachment.
#!/bin/bash
# requires: diff mail file nice imagemagick curl w3m cutycapt xvfb-run
argv0=webwatcher
XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache}
# default arguments
destination=your@face.com
mode=exact
while getopts :d:m: opt; do
case $opt in
d) destination=$OPTARG
;;
m) mode=$OPTARG
;;
*) echo "usage: ${0##*/} [+-mi} [--] ARGS..."
exit 2
esac
done
shift $(( OPTIND - 1 ))
OPTIND=1
if [[ ! $1 ]]; then
printf >&2 '%s\n' "$argv0: error: website not specified"
exit 2
fi
uri=$1
uri_id=$(sha256sum <<< "$1" | cut -d' ' -f1)
case $mode in
exact)
tmp_extension=.htm
# "small changes", may have false positives
ww_fetch() { curl -fsS "$1" --output "$2"; }
;;
text)
tmp_extension=.txt
# text-browser mode, may not render all contents
ww_fetch() { w3m -dump "$1" > "$2"; }
;;
image)
tmp_extension=.png
# browser mode, will render full page
# xvfb-run -a is used to allow multiple processes
ww_fetch() { nice -n 19 xvfb-run -a --server-args "-screen 0, 1024x768x24" \
cutycapt --url="$1" --out="$2"; }
;;
esac
# xdg base directory
known=$XDG_CACHE_HOME/$argv0/$uri_id$tmp_extension
mkdir -p "$XDG_CACHE_HOME/$argv0"
if [[ -s $known ]]; then
tmp=$(mktemp --suffix "$tmp_extension")
ww_fetch "$uri" "$tmp"
case $mode in
exact|text)
if ! diff -q "$known" "$tmp" >/dev/null; then
diff -u "$known" "$tmp" | mail -s "$argv0: changes for $1" "$destination"
mv "$tmp" "$known"
else
rm "$tmp"
fi ;;
image)
# when comparing screenshots, metadata has to be taken into account. See:
# http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html#C.Anc-text (PNG meta-data)
# http://www.imagemagick.org/Usage/compare/ ("IM Image Signatures", imagemagick)
image_signatures=()
while read -r sig; do
image_signatures+=("$REPLY")
done < <(identify -quiet -format '%#\n' "$tmp" "$known")
if [[ ${image_signatures[0]} != "${image_signatures[1]}" ]]; then
compare "$tmp" "$known" -compose src diff.png
mail -s "$argv0: changes for $1" "$destination" -A diff.png
mv "$tmp" "$known"
else
rm "$tmp"
fi ;;
esac
else
printf >&2 '%s\n' "$argv0: retrieving website for the first time"
ww_fetch "$uri" "$known"
fi
Last edited by Alad (2019-06-05 00:39:41)
Mods are just community members who have the occasionally necessary option to move threads around and edit posts. -- Trilby
Offline
Reading Alad's post above and seeing how he uses email for his notification system from his script has prompted me to recommend pushover.net which I have been using for a few years. E.g I have a personal script "notify-phone <message>" which I can call from scripts like the above (PS, I long ago wrote a similar "site-monitor" script myself). Pushover sends notifications direct to your phone, is extremely fast and reliable, and can be configured with different messages and priorities, i.e. with/without sound/pop up etc. You can create groups, so e.g my wife and I are in a "home alarm" group so our phones get instantly notified by my home alarm system (running on a Raspberry Pi using Arch ARM of course). That one is a high priority notification with a distinct sound and popup, which we must instantly deal with.
I normally avoid recommending any paid service but pushover only costs a single one-off "cup of coffee" for lifetime use of the client app. So it is a cheap, easy, and modern but reliable way to add phone notifications to your scripts and programs.
Offline
@Alad,
CutyCapt is executable name instead cutycapt, found in AUR: https://aur.archlinux.org/packages/cutycapt-qt5-git/
also the website url argument must be full eg: https://example.com
thanks for the script!
Offline
At the end of my .bash_profile
clear
wm() {
echo ""
echo ""
echo " MY DISPLAY MANAGER"
echo ""
echo ""
echo "Choose your window manager (defaults to i3)?"
echo "s) sway i) i3 k) kodi c) back to console or type command name (e.g., firefox)"
echo ""
echo "You can run this script again with command 'wm'"
echo ""
echo "Make your choice.:"
read wm
case $wm in
s|sway) sway ;;
i|i3) sx /usr/bin/i3 ;;
k|kodi) sx /usr/bin/kodi ;;
c) ;;
*) [ $wm ] && sx /usr/bin/$wm || sx /usr/bin/i3 ;;
esac
}
wm
Arch is home!
https://github.com/Docbroke
Offline
A little go script to play my favourite radio stations resiliently without buffer latency (uses MPV for playback)
package main
import (
"flag"
"fmt"
"io"
"log"
"net"
"net/http"
"os"
"os/exec"
"time"
)
func main() {
noskip := flag.Bool("noskip", false, "do not skip buffer")
flag.Usage = func() {
fmt.Println("help:")
fmt.Println("\tavailable stations")
fmt.Println("\t\t1, 2, 5, swh, heart")
fmt.Println("\t-noskip")
fmt.Println("\t\tdisables buffer skiping")
os.Exit(0)
}
flag.Parse()
stations := map[string]struct {
stream string
buffer int
bitrate int
codec string
}{
//Latvijas Radio 1,2,5
"1": {"http://lr1mp1.latvijasradio.lv:8010/", 15, 128, "aac"},
"2": {"http://lr2mp1.latvijasradio.lv:8000/", 15, 128, "aac"},
"5": {"http://live.pieci.lv/live19-hq.mp3", 3, 128, "mp3"},
//Radio SWH
"swh": {"http://87.110.219.34:8000/swhaac", 3, 128, "aac"},
//Heart London
"heart": {"http://media-ice.musicradio.com/HeartLondonMP3", 12, 128, "mp3"},
}
args := flag.Args()
// If no args, play LR2
station := stations["2"]
if len(args) > 0 {
if v, ok := stations[args[0]]; ok {
station = v
}
}
//Custom transport for IceCast protocol
tr := &http.Transport{
Dial: func(network, a string) (net.Conn, error) {
realConn, err := net.Dial(network, a)
if err != nil {
return nil, err
}
hijack := &IcyConnWrapper{
deadline: time.Second * 5,
Conn: realConn,
}
if *noskip {
hijack.deadline = time.Second * 15
}
return hijack, nil
},
}
client := &http.Client{
Transport: tr,
Timeout: time.Hour * 6,
}
http.DefaultClient = client
for {
stream, err := http.Get(station.stream)
if err != nil {
log.Println("GET:", err)
time.Sleep(time.Second * 5)
continue
}
pipe, err := getPipe(station.codec)
if err != nil {
log.Println("GETPIPE:", err)
time.Sleep(time.Second * 5)
continue
}
//Skip the buffer for more realtime playback
if !*noskip {
err := skipBytes(stream.Body, station.bitrate/8*1024*station.buffer)
if err != nil {
log.Println("SKIP BYTES:", err)
stream.Body.Close()
pipe.Close()
time.Sleep(time.Second * 5)
continue
}
}
//Fetch only half a second at a time
buf := make([]byte, station.bitrate/8*1024/2)
_, err = io.CopyBuffer(pipe, stream.Body, buf)
if err != nil {
log.Println("COPY BUFFER:", err)
stream.Body.Close()
pipe.Close()
time.Sleep(time.Second * 5)
}
}
}
//IcyConnWrapper makes IceCast to work with net/http package
type IcyConnWrapper struct {
net.Conn
haveReadAny bool
deadline time.Duration
}
func (i *IcyConnWrapper) Read(b []byte) (int, error) {
i.Conn.SetReadDeadline(time.Now().Add(i.deadline))
if i.haveReadAny {
return i.Conn.Read(b)
}
i.haveReadAny = true
//bounds checking ommitted. There are a few ways this can go wrong.
//always check array sizes and returned n.
n, err := i.Conn.Read(b[:3])
if err != nil {
return n, err
}
if string(b[:3]) == "ICY" {
//write Correct http response into buffer
copy(b, []byte("HTTP/1.1"))
return 8, nil
}
return n, nil
}
func skipBytes(i io.Reader, target int) error {
buf := make([]byte, 128)
total := 0
for {
n, err := i.Read(buf)
if err != nil {
return err
}
total += n
if total > target {
return nil
}
}
}
func getPipe(codec string) (pipe io.WriteCloser, err error) {
cmd := exec.Command("mpv", "-", "--profile=low-latency", "--quiet",
"--cache=no", "--demuxer-lavf-buffersize=512",
"--demuxer-lavf-format="+codec, "--demuxer=+lavf")
pipe, err = cmd.StdinPipe()
if err != nil {
return
}
statusOut, err := cmd.StdoutPipe()
if err != nil {
return
}
statusErr, err := cmd.StderrPipe()
if err != nil {
return
}
go func(src io.ReadCloser) {
io.Copy(os.Stdout, src)
}(statusOut)
go func(src io.ReadCloser) {
io.Copy(os.Stderr, src)
}(statusErr)
err = cmd.Start()
if err != nil {
return
}
go func(c *exec.Cmd) {
c.Wait()
log.Println("REALEASING MPV")
}(cmd)
return
}
Last edited by ugjka (2019-07-05 22:30:47)
https://ugjka.net
paru > yay | vesktop > discord
pacman -S spotify-launcher
mount /dev/disk/by-...
Offline
no shebang ?
is the kernel able to read your mind ?
Offline
no shebang ?
is the kernel able to read your mind ?
Go compiles to a statically linked binary executable
Last edited by ugjka (2019-06-29 21:29:18)
https://ugjka.net
paru > yay | vesktop > discord
pacman -S spotify-launcher
mount /dev/disk/by-...
Offline
ah, go !
you should have given a link (where) to go.
Offline
I emulated the rotate cube "screensaver" functionality compiz (0.9.x) lost many cycles ago, with xdotool and xprintidle:
#!/bin/bash
#Control this Xorg display
DISPLAY=:0.0
#Disable any input device other than XTEST and pointer
#pointer=12
#for i in $(xinput list --id-only); do \
# [[ "$i" -gt "5" ]] && [[ "$i" -ne "$pointer" ]] && \
# enabled="$(xinput list-props $i | grep "Device Enabled")" && \
# [[ "${enabled: -1}" -eq "1" ]] && \
# xinput disable "$i" && \
# disabled+=("$i"); \
#done
#Pixels to move mouse (rotates cube)
step=1
#Start rotation left or right at random
direction=$RANDOM; let "direction >>= 14"
[[ "$direction" -eq 1 ]] && direction=90 || direction=270
#Compiz rotate plugin's "initiate" button
xdotool mousedown 9 &
#Rotate Cube
while [ $(xprintidle) -gt 0 ]; do
xdotool mousemove_relative --polar "$direction" "$step" &
#Approximately 60fps
sleep 0.0165
done
#Compiz rotate plugin's "initiate" button
xdotool mouseup 9 &
#Enable any disabled input devices
#for i in "${disabled[@]}"; do \
# xinput enable "$i" & \
#done
UPDATE: Added xinput to disable devices while screensaver is active; one pointer needs to be excepted (your usual mouse) to break out of the screensaver. Not sure of a way to correlate the pointer device one uses most to a specific xinput number, so commented out (find this number by name or trial and error with xinput {list,disable n,enable n}).
Last edited by quequotion (2020-01-12 14:40:47)
makepkg-optimize · indicator-powersave · pantheon-{3d,lite} · {pantheon,higan}-qq
Offline
ah, go !
you should have given a link (where) to go.
There is a way to execute it as a script though: https://blog.cloudflare.com/using-go-as … -in-linux/
https://ugjka.net
paru > yay | vesktop > discord
pacman -S spotify-launcher
mount /dev/disk/by-...
Offline
Vpn via ssh with routed traffic, it could be done a lot better, and seems to require superuser rights on the local and remote side ; of course key authentication is needed, but it is still definitely nice:
TUNIP_L=192.168.244.2 #local vpn ip
TUNIP_R=192.168.244.1 #remote vpn ip
DEF_GW=192.168.15.1 #default local gateway
SSHD=<remote ip> #remote ssh server
SSHDP=22 #remote ssh server port
sh -c "sleep 5 ; \
route add -net 0.0.0.0 netmask 0.0.0.0 gw $TUNIP_R ; \
route add $SSHD gw $DEF_GW ; \
echo routed" &
ssh \
-o PermitLocalCommand=yes \
-o LocalCommand="sudo ifconfig tun5 $TUNIP_L pointopoint $TUNIP_R netmask 255.255.255.0" \
-o ServerAliveInterval=60 \
-w 5:5 root@$SSHD -p $SSHDP \
"sudo ifconfig tun5 $TUNIP_R pointopoint $TUNIP_R netmask 255.255.255.0; echo tun ready"
route del -net 0.0.0.0 netmask 0.0.0.0 gw $TUNIP_R ; route del $SSHD gw $DEF_GW
echo unrouted
on the ssh server (it could be done even in the previous command):
iptables -t nat -A POSTROUTING -s 192.0.0.0/24 -o etha0a9 -j MASQUERADE
Do i really need openvpn?
Last edited by kokoko3k (2019-07-09 18:07:01)
Help me to improve ssh-rdp !
Retroarch User? Try my koko-aio shader !
Offline
ah, go !
you should have given a link (where) to go.
He said it's a go script. Dunno what else you'd need to know.
Offline
Added help function on zshbuiltins in ~/.zsh_functions:
## zshbuiltins help by paragraph
helpz()
{
[[ -z $* ]] && echo "give argument among these : " &&
ls /usr/share/zsh/*/help/ || less /usr/share/zsh/*/help/$*
}
without argument gives list and with one shows help, more readable than man zshbuiltins
Last edited by waitnsea (2019-08-09 04:52:30)
Offline
??? ⏹??? ?????? ?⏹? ???? ???? ????: ?????? ?⏹?? ??????? ?⏹ ????⏹? ??⏹???!
("The only script you will ever need: Change your letters to random emojis!") - I'm not sure if this forum will display the emojis though.. Here's a screenshot:
#!/bin/bash
declare -a keycodes=("24" "25" "26" "27" "28" "29" "30" "31" "32" "33" "34" "38" "39" "40" "41" "42" "43" "44" "45" "46" "47" "48" "52" "53" "54" "55" "56" "57" "58")
declare -a emojis=("3299" "1F004" "1F0CF" "1F170" "1F171" "1F17E" "1F17F" "1F18E" "1F191" "1F192" "1F193" "1F194" "1F195" "1F196" "1F197" "1F198" "1F199" "1F19A" "1F1E6" "1F1E7" "1F1E8" "1F1E9" "1F1EA" "1F1EB" "1F1EC" "1F1ED" "1F1EE" "1F1EF" "1F1F0" "1F1F1" "1F1F2" "1F1F3" "1F1F4" "1F1F5" "1F1F6" "1F1F7" "1F1F8" "1F1F9" "1F1FA" "1F1FB" "1F1FC" "1F1FD" "1F1FE" "1F1FF" "1F201" "1F202" "1F21A" "1F22F" "1F232" "1F233" "1F234" "1F235" "1F236" "1F237" "1F238" "1F239" "1F23A" "1F250" "1F251" "1F300" "1F301" "1F302" "1F303" "1F304" "1F305" "1F306" "1F307" "1F308" "1F309" "1F30A" "1F30B" "1F30C" "1F30D" "1F30E" "1F30F" "1F310" "1F311" "1F312" "1F313" "1F314" "1F315" "1F316" "1F317" "1F318" "1F319" "1F31A" "1F31B" "1F31C" "1F31D" "1F31E" "1F31F" "1F320" "1F321" "1F324" "1F325" "1F326" "1F327" "1F328" "1F329" "1F32A" "1F32B" "1F32C" "1F32D" "1F32E" "1F32F" "1F330" "1F331" "1F332" "1F333" "1F334" "1F335" "1F336" "1F337" "1F338" "1F339" "1F33A" "1F33B" "1F33C" "1F33D" "1F33E" "1F33F" "1F340" "1F341" "1F342" "1F343" "1F344" "1F345" "1F346" "1F347" "1F348" "1F349" "1F34A" "1F34B" "1F34C" "1F34D" "1F34E" "1F34F" "1F350" "1F351" "1F352" "1F353" "1F354" "1F355" "1F356" "1F357" "1F358" "1F359" "1F35A" "1F35B" "1F35C" "1F35D" "1F35E" "1F35F" "1F360" "1F361" "1F362" "1F363" "1F364" "1F365" "1F366" "1F367" "1F368" "1F369" "1F36A" "1F36B" "1F36C" "1F36D" "1F36E" "1F36F" "1F370" "1F371" "1F372" "1F373" "1F374" "1F375" "1F376" "1F377" "1F378" "1F379" "1F37A" "1F37B" "1F37C" "1F37D" "1F37E" "1F37F" "1F380" "1F381" "1F382" "1F383" "1F384" "1F385" "1F386" "1F387" "1F388" "1F389" "1F38A" "1F38B" "1F38C" "1F38D" "1F38E" "1F38F" "1F390" "1F391" "1F392" "1F393" "1F396" "1F397" "1F399" "1F39A" "1F39B" "1F39E" "1F39F" "1F3A0" "1F3A1" "1F3A2" "1F3A3" "1F3A4" "1F3A5" "1F3A6" "1F3A7" "1F3A8" "1F3A9" "1F3AA" "1F3AB" "1F3AC" "1F3AD" "1F3AE" "1F3AF" "1F3B0" "1F3B1" "1F3B2" "1F3B3" "1F3B4" "1F3B5" "1F3B6" "1F3B7" "1F3B8" "1F3B9" "1F3BA" "1F3BB" "1F3BC" "1F3BD" "1F3BE" "1F3BF" "1F3C0" "1F3C1" "1F3C2" "1F3C3" "1F3C4" "1F3C5" "1F3C6" "1F3C7" "1F3C8" "1F3C9" "1F3CA" "1F3CB" "1F3CC" "1F3CD" "1F3CE" "1F3CF" "1F3D0" "1F3D1" "1F3D2" "1F3D3" "1F3D4" "1F3D5" "1F3D6" "1F3D7" "1F3D8" "1F3D9" "1F3DA" "1F3DB" "1F3DC" "1F3DD" "1F3DE" "1F3DF" "1F3E0" "1F3E1" "1F3E2" "1F3E3" "1F3E4" "1F3E5" "1F3E6" "1F3E7" "1F3E8" "1F3E9" "1F3EA" "1F3EB" "1F3EC" "1F3ED" "1F3EE" "1F3EF" "1F3F0" "1F3F3" "1F3F4" "1F3F5" "1F3F7" "1F3F8" "1F3F9" "1F3FA" "1F400" "1F401" "1F402" "1F403" "1F404" "1F405" "1F406" "1F407" "1F408" "1F409" "1F40A" "1F40B" "1F40C" "1F40D" "1F40E" "1F40F" "1F410" "1F411" "1F412" "1F413" "1F414" "1F415" "1F416" "1F417" "1F418" "1F419" "1F41A" "1F41B" "1F41C" "1F41D" "1F41E" "1F41F" "1F420" "1F421" "1F422" "1F423" "1F424" "1F425" "1F426" "1F427" "1F428" "1F429" "1F42A" "1F42B" "1F42C" "1F42D" "1F42E" "1F42F" "1F430" "1F431" "1F432" "1F433" "1F434" "1F435" "1F436" "1F437" "1F438" "1F439" "1F43A" "1F43B" "1F43C" "1F43D" "1F43E" "1F43F" "1F440" "1F441" "1F442" "1F443" "1F444" "1F445" "1F446" "1F447" "1F448" "1F449" "1F44A" "1F44B" "1F44C" "1F44D" "1F44E" "1F44F" "1F450" "1F451" "1F452" "1F453" "1F454" "1F455" "1F456" "1F457" "1F458" "1F459" "1F45A" "1F45B" "1F45C" "1F45D" "1F45E" "1F45F" "1F460" "1F461" "1F462" "1F463" "1F464" "1F465" "1F466" "1F467" "1F468" "1F469" "1F46A" "1F46B" "1F46C" "1F46D" "1F46E" "1F46F" "1F470" "1F471" "1F472" "1F473" "1F474" "1F475" "1F476" "1F477" "1F478" "1F479" "1F47A" "1F47B" "1F47C" "1F47D" "1F47E" "1F47F" "1F480" "1F481" "1F482" "1F483" "1F484" "1F485" "1F486" "1F487" "1F488" "1F489" "1F48A" "1F48B" "1F48C" "1F48D" "1F48E" "1F48F" "1F490" "1F491" "1F492" "1F493" "1F494" "1F495" "1F496" "1F497" "1F498" "1F499" "1F49A" "1F49B" "1F49C" "1F49D" "1F49E" "1F49F" "1F4A0" "1F4A1" "1F4A2" "1F4A3" "1F4A4" "1F4A5" "1F4A6" "1F4A7" "1F4A8" "1F4A9" "1F4AA" "1F4AB" "1F4AC" "1F4AD" "1F4AE" "1F4AF" "1F4B0" "1F4B1" "1F4B2" "1F4B3" "1F4B4" "1F4B5" "1F4B6" "1F4B7" "1F4B8" "1F4B9" "1F4BA" "1F4BB" "1F4BC" "1F4BD" "1F4BE" "1F4BF" "1F4C0" "1F4C1" "1F4C2" "1F4C3" "1F4C4" "1F4C5" "1F4C6" "1F4C7" "1F4C8" "1F4C9" "1F4CA" "1F4CB" "1F4CC" "1F4CD" "1F4CE" "1F4CF" "1F4D0" "1F4D1" "1F4D2" "1F4D3" "1F4D4" "1F4D5" "1F4D6" "1F4D7" "1F4D8" "1F4D9" "1F4DA" "1F4DB" "1F4DC" "1F4DD" "1F4DE" "1F4DF" "1F4E0" "1F4E1" "1F4E2" "1F4E3" "1F4E4" "1F4E5" "1F4E6" "1F4E7" "1F4E8" "1F4E9" "1F4EA" "1F4EB" "1F4EC" "1F4ED" "1F4EE" "1F4EF" "1F4F0" "1F4F1" "1F4F2" "1F4F3" "1F4F4" "1F4F5" "1F4F6" "1F4F7" "1F4F8" "1F4F9" "1F4FA" "1F4FB" "1F4FC" "1F4FD" "1F4FF" "1F500" "1F501" "1F502" "1F503" "1F504" "1F505" "1F506" "1F507" "1F508" "1F509" "1F50A" "1F50B" "1F50C" "1F50D" "1F50E" "1F50F" "1F510" "1F511" "1F512" "1F513" "1F514" "1F515" "1F516" "1F517" "1F518" "1F519" "1F51A" "1F51B" "1F51C" "1F51D" "1F51E" "1F51F" "1F520" "1F521" "1F522" "1F523" "1F524" "1F525" "1F526" "1F527" "1F528" "1F529" "1F52A" "1F52B" "1F52C" "1F52D" "1F52E" "1F52F" "1F530" "1F531" "1F532" "1F533" "1F534" "1F535" "1F536" "1F537" "1F538" "1F539" "1F53A" "1F53B" "1F53C" "1F53D" "1F549" "1F54A" "1F54B" "1F54C" "1F54D" "1F54E" "1F550" "1F551" "1F552" "1F553" "1F554" "1F555" "1F556" "1F557" "1F558" "1F559" "1F55A" "1F55B" "1F55C" "1F55D" "1F55E" "1F55F" "1F560" "1F561" "1F562" "1F563" "1F564" "1F565" "1F566" "1F567" "1F56F" "1F570" "1F573" "1F574" "1F575" "1F576" "1F577" "1F578" "1F579" "1F57A" "1F587" "1F58A" "1F58B" "1F58C" "1F58D" "1F590" "1F595" "1F596" "1F5A4" "1F5A5" "1F5A8" "1F5B1" "1F5B2" "1F5BC" "1F5C2" "1F5C3" "1F5C4" "1F5D1" "1F5D2" "1F5D3" "1F5DC" "1F5DD" "1F5DE" "1F5E1" "1F5E3" "1F5E8" "1F5EF" "1F5F3" "1F5FA" "1F5FB" "1F5FC" "1F5FD" "1F5FE" "1F5FF" "1F600" "1F601" "1F602" "1F603" "1F604" "1F605" "1F606" "1F607" "1F608" "1F609" "1F60A" "1F60B" "1F60C" "1F60D" "1F60E" "1F60F" "1F610" "1F611" "1F612" "1F613" "1F614" "1F615" "1F616" "1F617" "1F618" "1F619" "1F61A" "1F61B" "1F61C" "1F61D" "1F61E" "1F61F" "1F620" "1F621" "1F622" "1F623" "1F624" "1F625" "1F626" "1F627" "1F628" "1F629" "1F62A" "1F62B" "1F62C" "1F62D" "1F62E" "1F62F" "1F630" "1F631" "1F632" "1F633" "1F634" "1F635" "1F636" "1F637" "1F638" "1F639" "1F63A" "1F63B" "1F63C" "1F63D" "1F63E" "1F63F" "1F640" "1F641" "1F642" "1F643" "1F644" "1F645" "1F646" "1F647" "1F648" "1F649" "1F64A" "1F64B" "1F64C" "1F64D" "1F64E" "1F64F" "1F680" "1F681" "1F682" "1F683" "1F684" "1F685" "1F686" "1F687" "1F688" "1F689" "1F68A" "1F68B" "1F68C" "1F68D" "1F68E" "1F68F" "1F690" "1F691" "1F692" "1F693" "1F694" "1F695" "1F696" "1F697" "1F698" "1F699" "1F69A" "1F69B" "1F69C" "1F69D" "1F69E" "1F69F" "1F6A0" "1F6A1" "1F6A2" "1F6A3" "1F6A4" "1F6A5" "1F6A6" "1F6A7" "1F6A8" "1F6A9" "1F6AA" "1F6AB" "1F6AC" "1F6AD" "1F6AE" "1F6AF" "1F6B0" "1F6B1" "1F6B2" "1F6B3" "1F6B4" "1F6B5" "1F6B6" "1F6B7" "1F6B8" "1F6B9" "1F6BA" "1F6BB" "1F6BC" "1F6BD" "1F6BE" "1F6BF" "1F6C0" "1F6C1" "1F6C2" "1F6C3" "1F6C4" "1F6C5" "1F6CB" "1F6CC" "1F6CD" "1F6CE" "1F6CF" "1F6D0" "1F6D1" "1F6D2" "1F6E0" "1F6E1" "1F6E2" "1F6E3" "1F6E4" "1F6E5" "1F6E9" "1F6EB" "1F6EC" "1F6F0" "1F6F3" "1F6F4" "1F6F5" "1F6F6" "1F6F7" "1F6F8" "1F910" "1F911" "1F912" "1F913" "1F914" "1F915" "1F916" "1F917" "1F918" "1F919" "1F91A" "1F91B" "1F91C" "1F91D" "1F91E" "1F91F" "1F920" "1F921" "1F922" "1F923" "1F924" "1F925" "1F926" "1F927" "1F928" "1F929" "1F92A" "1F92B" "1F92C" "1F92D" "1F92E" "1F92F" "1F930" "1F931" "1F932" "1F933" "1F934" "1F935" "1F936" "1F937" "1F938" "1F939" "1F93A" "1F93C" "1F93D" "1F93E" "1F940" "1F941" "1F942" "1F943" "1F944" "1F945" "1F947" "1F948" "1F949" "1F94A" "1F94B" "1F94C" "1F950" "1F951" "1F952" "1F953" "1F954" "1F955" "1F956" "1F957" "1F958" "1F959" "1F95A" "1F95B" "1F95C" "1F95D" "1F95E" "1F95F" "1F960" "1F961" "1F962" "1F963" "1F964" "1F965" "1F966" "1F967" "1F968" "1F969" "1F96A" "1F96B" "1F980" "1F981" "1F982" "1F983" "1F984" "1F985" "1F986" "1F987" "1F988" "1F989" "1F98A" "1F98B" "1F98C" "1F98D" "1F98E" "1F98F" "1F990" "1F991" "1F992" "1F993" "1F994" "1F995" "1F996" "1F997" "1F9C0" "1F9D0" "1F9D1" "1F9D2" "1F9D3" "1F9D4" "1F9D5" "1F9D6" "1F9D7" "1F9D8" "1F9D9" "1F9DA" "1F9DB" "1F9DC" "1F9DD" "1F9DE" "1F9DF" "1F9E0" "1F9E1" "1F9E2" "1F9E3" "1F9E4" "1F9E5" "1F9E6" "203C" "2049" "2122" "2139" "2194" "2195" "2196" "2197" "2198" "2199" "21A9" "21AA" "231A" "231B" "2328" "23CF" "23E9" "23EA" "23EB" "23EC" "23ED" "23EE" "23EF" "23F0" "23F1" "23F2" "23F3" "23F8" "23F9" "23FA" "24C2" "25AA" "25AB" "25B6" "25C0" "25FB" "25FC" "25FD" "25FE" "2600" "2601" "2602" "2603" "2604" "260E" "2611" "2614" "2615" "2618" "261D" "2620" "2622" "2623" "2626" "262A" "262E" "262F" "2638" "2639" "263A" "2640" "2642" "2648" "2649" "264A" "264B" "264C" "264D" "264E" "264F" "2650" "2651" "2652" "2653" "2660" "2663" "2665" "2666" "2668" "267B" "267F" "2692" "2693" "2694" "2695" "2696" "2697" "2699" "269B" "269C" "26A0" "26A1" "26AA" "26AB" "26B0" "26B1" "26BD" "26BE" "26C4" "26C5" "26C8" "26CE" "26CF" "26D1" "26D3" "26D4" "26E9" "26EA" "26F0" "26F1" "26F2" "26F3" "26F4" "26F5" "26F7" "26F8" "26F9" "26FA" "26FD" "2702" "2705" "2708" "2709" "270A" "270B" "270C" "270D" "270F" "2712" "2714" "2716" "271D" "2721" "2728" "2733" "2734" "2744" "2747" "274C" "274E" "2753" "2754" "2755" "2757" "2763" "2764" "2795" "2796" "2797" "27A1" "27B0" "27BF" "2934" "2935" "2B05" "2B06" "2B07" "2B1B" "2B1C" "2B50" "2B55" "3030" "303D" "3297")
len=${#emojis[@]}
for i in "${keycodes[@]}"; do
n=$(($RANDOM % len))
g=$(($RANDOM % len))
xmodmap -e "keycode ${i} = U${emojis[$n]} U${emojis[$g]}"
done
Self explanatory I think. You might want to backup your keymap (xmodmap -pke > xmm.txt) to restore (xmodmap xmm.txt) it later. All changes are temporary (-e).
#!/bin/bash
xclip -selection clipboard -target image/png -i "/path/to/image.png"
Copies an image as such into the clipboard. Useful to set as shortcut if you frequently use an image on social media (e.g. Discord).
#!/bin/bash
if [[ $1 == "" ]]; then
echo "Please supply a file to play."
exit 1
fi
frp=$(realpath "$1")
if [[ $2 == "f" ]]; then
fwidth="100%"
fheight="100%"
bpb=""
else
fwidth=$(mediainfo --output=JSON "${frp}" | jq . | grep "Width" | cut -d '"' -f 4)
fheight=$(mediainfo --output=JSON "${frp}" | jq . | grep "Height" | cut -d '"' -f 4)
bpb="<br></br>"
fi
echo "<style>html{ background-color: #232323; }</style><center>${bpb}<embed src='${frp}' type='application/x-shockwave-flash' width='${fwidth}' height='${fheight}' quality='high'></center>" > /tmp/cflashplayer.html
firefox --new-tab /tmp/cflashplayer.html
For all of those getting mad over firefox not playing your .swf files and instead just wanting to download them. A crude yet nice .SWF player (uses firefox). Supply "f" as second argument for fullscreen. Requires jq and mediainfo.
Offline
Someone may have use for the following small script I wrote, for use with a yubikey/crypto device:
#!/bin/bash
function genhelp () {
echo -e "$0 <lock/unlock/relock>"
exit 1
}
if [ $# -eq 0 ]; then genhelp; fi
if [[ "$1" == "lock" ]]; then
rm -rf /tmp/netacct-*
elif [[ "$1" == "unlock" ]]; then
rm -rf /tmp/netacct-*
tmpd=$(mktemp -p /tmp -d netacct-XXXXXXXX)
gpgtar -C "$tmpd" --decrypt /home/usr/files/ncred 1>/dev/null 2>/dev/null
echo "$tmpd"
elif [[ "$1" == "relock" ]]; then
tdir=$(find '/tmp/' -maxdepth 1 -type d -name 'netacct-*' -print -quit)
if [[ -z "$tdir" ]]; then
echo "Credentials not found, exiting"
exit 1
fi
gpgtar -C "$tdir" --encrypt --output /home/usr/files/ncred --recipient XXXXXXX z1
else
genhelp
fi
I have all of my passwords stored in individual files, for each online website I have a username/password with. I utilize this script to simply decrypt the files in one swoop, re-encrypt the password files back into the original gpg'd tar archive, and to remove the temporary directory in /tmp. Currently, my yubikey stick is set up with a main unlock passcode, so when this script is executed, it will prompt for the code. After the first time, it will be stored in the keyring. I also have a udev script set up to remote the decrypted files when the yubikey stick is removed, as follows: (stored in /etc/udev/rules.d/XX-name.rules)
ACTION=="remove", ENV{ID_MODEL}=="Yubikey_4_OTP+U2F+CCID", ENV{ID_VENDOR_ID}=="1050", ENV{ID_MODEL_ID}=="0407", RUN+="/usr/local/bin/netaccts lock"
Cheers to anyone who uses this, or makes this better.
Offline
A case statement could clean that up:
#!/bin/bash
case $1 in
unlock)
rm -rf /tmp/netacct-*
tmpd=$(mktemp -p /tmp -d netacct-XXXXXXXX)
gpgtar -C "$tmpd" --decrypt /home/usr/files/ncred 1>/dev/null 2>&1
echo "$tmpd"
;;
relock)
tdir=$(find '/tmp/' -maxdepth 1 -type d -name 'netacct-*' -print -quit)
if [[ -z "$tdir" ]]; then
echo "Credentials not found, exiting"
exit 1
fi
gpgtar -C "$tdir" --encrypt --output /home/usr/files/ncred --recipient XXXXXXX z1
;&
lock)
rm -rf /tmp/netacct-*
;;
*)
echo -e "$0 <lock/unlock/relock>"
exit 1
esac
Note I changed the logic slightly so that relock also removes /tmp/netacct-*. Given that you are "relocking" it should end up in a locked state. If you don't want this, then just add back a ';;' terminator for the relock case which currently falls through to the lock case.
EDIT: apparently fallthrough only works in BASH and has a funky terminating symbol ';&'. I could have sworn I used case-statement fallthrough in shells before just by omitting the ';;', perhaps I'm remembering incorrectly.
Last edited by Trilby (2019-09-30 00:25:49)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Online
Trilby, thanks for that. And yeah, I know, I should probably use case statements more. Thanks more for informing me about the fall back feature, didn't know about that! I heavily/extensively use zsh, would it be any different?
Offline
I don't know zsh at all - when I first wrote the above code I thought fallthrough was in all shells, but was wrong (it's a C thing I guess and recently added to BASH).
Without the fallthrough, though, you'd only duplicate the one rm line.
Using a case with a default case is what really simplifies it so you don't need to check multiple times on whether the help output should be displayed.
Last edited by Trilby (2019-09-30 17:50:09)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Online
Yet another tts script, based on this.
tts:
#!/bin/bash
textin="/tmp/.tts-in" && [[ ! -p "${textin}" ]] && mkfifo -m 600 "${textin}"
wavout="/tmp/.tts-out" && [[ ! -p "${wavout}" ]] && mkfifo -m 600 "${wavout}"
htsvoice="/usr/share/hts/voices/english/cmu_us_arctic_slt.htsvoice" && \
[[ ! -f "${htsvoice}" ]] && echo "HTS voice not available" && exit 1
while IFS= read -r line; do
echo "${line}" > "${textin}" &
flite_hts_engine -m "${htsvoice}" \
-s 48000 -r 1.3 -fm 0 \
"${textin}" -o "${wavout}" &
paplay -d Center-Mono "${wavout}"
done <<< "${@}"
This was easier for me than patching flite_hts_engine to use stdio.
paplay is better at guessing the audio format than aplay, and allows to send the output to any pulseaudio sink. "Center-Mono" is a remapped (virtual) sink on a digital 5.1 output, using only the center channel.
/etc/pulse/default.pa (excerpt):
#Center mono
load-module module-remap-sink sink_name=Center-Mono sink_properties="device.description='Center Mono (5.1 AC3 on ALC892 Digital)' media.name='Center-Mono'" master=alsa_output.pci-0000_00_1b.0.iec958-ac3-surround-51 channels=1 master_channel_map=center channel_map=mono
Edit: Subsequently, rewrote dmesg-speak!
Last edited by quequotion (2019-10-06 09:38:10)
makepkg-optimize · indicator-powersave · pantheon-{3d,lite} · {pantheon,higan}-qq
Offline
On my notebook KDE changing screen brightness too hard, wanted smooth change like in windows, so made script
arguments: [number of steps] [single step amount]
bind it to brightness keys as
~/backlight 10 2
~/backlight -10 2
#!/usr/bin/bash
Amount=${1}
Inc=${2:-1}
function getbacklight {
qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightness
}
function setbacklight {
qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.setBrightness "$1"
}
if ((${Amount} < 0));
then
Inc=$((-$Inc))
Amount=$((-$Amount))
fi
for (( i = 0; i <= ${Amount}; i++ )) ; do
setbacklight $(($(getbacklight) + $Inc))
done
Last edited by avi9526 (2019-11-10 02:50:00)
Offline