Skip to content

Instantly share code, notes, and snippets.

@isoraqathedh
Last active January 27, 2025 09:29
Show Gist options
  • Save isoraqathedh/d93b1d90485784fab62b5e9e2ff34b75 to your computer and use it in GitHub Desktop.
Save isoraqathedh/d93b1d90485784fab62b5e9e2ff34b75 to your computer and use it in GitHub Desktop.
from enum import Enum
import yaml
import pytesseract
import re
import io
import os
from PIL import Image
import subprocess
def clipboard():
if re.search(
"image/",
subprocess.run(
["xclip", "-sel", "c", "-target", "TARGETS", "-out"],
capture_output=True).stdout.decode("UTF-8")):
return Image.open(
io.BytesIO(
subprocess.run(
["xclip", "-sel", "c", "-target", "image/png", "-out"],
capture_output=True).stdout))
else:
return subprocess.run(
["xclip", "-sel", "c", "-out"],
capture_output=True).stdout.decode("UTF-8")
def next_clipboard(prompt=None):
if prompt:
print(prompt)
subprocess.run("clipnotify")
return clipboard()
class DetectionType(Enum):
TEXT = "text"
IMAGE = "image"
class Game:
name = None
target = None
text_target = None
detection = DetectionType.TEXT
refresh_hour = 0
out_filename = []
date = datetime.today().strftime("%Y-%m-%d")
@classmethod
def from_dict(cls, d):
inst = cls()
dat = {
"detection": DetectionType.TEXT,
"refresh_hour": 0,
"out_filename": [f"{d['name'].lower()}-{inst.date}.txt"],
"name": None,
"target": None,
"text_target": None,
} | d
inst.name = dat["name"]
inst.detection = DetectionType(dat["detection"])
inst.refresh_hour = dat["refresh_hour"]
inst.target = re.compile(dat["target"])
if "text_target" in dat and dat['text_target']:
inst.text_target = re.compile(dat["text_target"])
if isinstance(dat['out_filename'], list) and len(dat['out_filename']) > 0:
inst.out_filename = [i.format(date=inst.date) for i in dat['out_filename']]
elif isinstance(dat['out_filename'], str):
inst.out_filename = [dat['out_filename'].format(date=inst.date)]
else:
raise ValueError(
f"Cannot create a list of output filenames out of {dat['out_filename']}"
)
if not (inst.name and inst.target):
raise ValueError("name and target must be defined.")
return inst
def __repr__(self):
return "<{class_name} {game_name}{collectedp}>".format(
class_name=type(self).__qualname__,
game_name=str(self.name),
collectedp=" collected" if self.collectedp() else "",
)
def collectedp(self):
return all(os.path.isfile(x) for x in self.out_filename)
def collect_if_match(self, thing):
if self.collectedp():
return None
elif self.detection == DetectionType.TEXT and isinstance(thing, str):
matchp = self.target.search(thing)
if matchp:
with open(self.out_filename[0], 'w') as f:
f.write(thing)
f.write("\n")
return self
elif self.detection == DetectionType.IMAGE and isinstance(thing, Image.Image):
matchp = self.target.search(pytesseract.image_to_string(thing))
if matchp:
thing.save(next(x for x in self.out_filename if x.endswith(".png")))
while True:
clipboard = next_clipboard()
if isinstance(clipboard, str) and self.text_target.search(clipboard):
with open(next(x for x in self.out_filename
if x.endswith(".txt")),
'w') as f:
f.write(clipboard)
f.write("\n")
return self
else:
return None
class GameCollection:
collection = []
def __init__(self, collection):
self.collection = collection
def __repr__(self):
return f"<{type(self).__qualname__}, {len(self.collection)} entries>"
@classmethod
def from_yaml_file(cls, filename):
with open(filename) as f:
dat = yaml.load(f, yaml.SafeLoader)
return cls([Game.from_dict(i) for i in dat])
def report_status(self):
count = 0
for i in self.collection:
if i.collectedp():
print(f" {i.name} ✓")
count += 1
else:
print(f"> {i.name} ✗")
print(f"{count} of {len(self.collection)} collected")
def completep(self):
return all(x.collectedp() for x in self.collection)
def get(self, game_name):
return next(x for x in self.collection if x.name == game_name)
def find_matching_game(self, thing):
for i in self.collection:
res = i.collect_if_match(thing)
if res:
return res
return None
def collect(self):
while not collection.completep():
try:
res = collection.find_matching_game(next_clipboard())
if res:
print(res)
except KeyboardInterrupt:
collection.report_status()
break
return self
def clipboard():
if re.search(
"image/",
subprocess.run(
["xclip", "-sel", "c", "-target", "TARGETS", "-out"],
capture_output=True).stdout.decode("UTF-8")):
return Image.open(
io.BytesIO(
subprocess.run(
["xclip", "-sel", "c", "-target", "image/png", "-out"],
capture_output=True).stdout))
else:
return subprocess.run(
["xclip", "-sel", "c", "-out"],
capture_output=True).stdout.decode("UTF-8")
def next_clipboard(prompt=None):
if prompt:
print(prompt)
subprocess.run("clipnotify")
return clipboard()
if __name__ == "__main__":
collection = GameCollection.from_yaml_file("games.yaml")
while not collection.completep():
try:
collection.collect_next_clipboard()
except KeyboardInterrupt:
break
#!/bin/zsh
today=$(date --date="${1-today}" +%Y-%m-%d)
collect=(0 0 0 0 0 0 0 0 0 0)
pst -n "Detecting already-present results..."
if [[ -f $today.png ]]; then
pst -e "Today's results are already collected."
exit 1
fi
if [[ -f nerdle-$today.txt ]]; then
echo "Nerdle ✓"
collect[1]=1
else echo "> Nerdle ✗"; fi
if [[ -f binerdle-$today.txt ]]; then
echo "Binerdle ✓";
collect[7]=1
else echo "> Binderdle ✗"; fi
if [[ -f lukhap-$today.txt ]]; then
echo "Lukhap ✓"
collect[2]=1
else echo "> Lukhap ✗" ; fi
if [[ -f mjhandle-$today.txt ]]; then
echo "Mahjong handle ✓"
collect[3]=1
else echo "> Mahjong Handle ✗" ; fi
if [[ -f zidou-$today.txt ]]; then
echo "Zidou ✓"
collect[4]=1
else echo "> Zidou ✗" ; fi
if [[ -f diffle-$today.png && -s diffle-$today.png ]]; then
echo "Diffle ✓"
collect[5]=1
else echo "> Diffle ✗"; fi
if [[ -f tetsudoru-$today.txt ]]; then
echo "Tetsudoru ✓"
collect[6]=1
else echo "> Tetsudoru ✗"; fi
if [[ -f redactle-$today.txt ]]; then
echo "Redactle ✓"
collect[8]=1
else echo "> Redactle ✗"; fi
if [[ -f celltower-$today.txt ]]; then
echo "Cell Tower ✓"
collect[9]=1
else echo "> Cell Tower ✗"; fi
if [[ -f hexcodle-$today.txt ]]; then
echo "Hexcodle ✓"
collect[10]=1
else echo "> Hexcodle ✗"; fi
# if [[ -f scrabble-$today.png && -s scrabble-$today.png ]]; then
# echo "Scrabble ✓"
# collect[10]=1
# else echo "> Scrabble ✗"; fi
# Collect clipboard scores
interrupted=0
trap 'tput cnorm; interrupted=1; pkill clipnotify' INT TERM
pst -n "Collecting scores... (Press C-c to cancel)"
while [[ $(( ${collect[@]/%/ +} 0)) -lt ${#collect} ]] ; do
echo -n "\033[2K\r"$(( ${collect[@]/%/ +} 0)) of ${#collect} collected" "
clipnotify
if [[ $interrupted == 1 ]]; then
trap - INT TERM
echo "\nCollection terminated"
break
fi
if xclip -sel c -target TARGETS -out | grep -q image/; then
# Image, use OCR to check if it's Diffle or Scrabble:
xclip -sel c -target image/png -out |
tesseract --dpi 315 - - |
tr -d \'\" |
xargs echo |
case $(cat) in
DIFFLE*)
[[ ${collect[5]} == 1 ]] && continue
# Diffle
xclip -sel c -target image/png -out > diffle-$today.png
if [[ ! -s diffle-$today.png ]]; then
continue
fi
collect[5]=1
echo -e "\rStored diffle-$today.png"
paplay ~/.local/share/sounds/ready.mp3 # Cue ready to accept text
echo "Copy Diffle text data also:"
while clipnotify; do
xclip -sel c -target UTF8_STRING -out |
if grep -q Diffle; then
xclip -sel c -target UTF8_STRING -out |
sed '/^https:/d;$a\' > diffle-$today.txt
echo "Stored diffle-$today.txt"
break
fi
done
;;
*)
echo -ne "Not a recognised variant, skipping\r"
continue
esac
elif xclip -sel c -target TARGETS -out | grep -q STRING; then
xclip -sel c -target UTF8_STRING -out | case $(head -n 1) in
nerdlegame*)
[[ ${collect[1]} == 1 ]] && continue
out="nerdle-$today.txt"
collect[1]=1
;;
binerdle*)
[[ ${collect[7]} == 1 ]] && continue
out="binerdle-$today.txt"
collect[7]=1
;;
"六合"*)
[[ ${collect[2]} == 1 ]] && continue
out="lukhap-$today.txt"
collect[2]=1
;;
"Mahjong Handle"*)
[[ ${collect[3]} == 1 ]] && continue
out="mjhandle-$today.txt"
collect[3]=1
;;
Zidou*)
[[ ${collect[4]} == 1 ]] && continue
out="zidou-$today.txt"
collect[4]=1
;;
"#テツドル"*)
[[ ${collect[6]} == 1 ]] && continue
out="tetsudoru-$today.txt"
collect[6]=1
;;
"I solved Redactle"*)
[[ ${collect[8]} == 1 ]] && continue
out="redactle-$today.txt"
collect[8]=1
;;
"I got Hexcodle"*)
[[ ${collect[10]} == 1 ]] && continue
out="hexcodle-$today.txt"
collect[10]=1
;;
\#CellTower*)
[[ ${collect[9]} == 1 ]] && continue
out="celltower-$today.txt"
collect[9]=1
;;
*)
echo -ne " Not a recognised variant, skipping\r"
continue
esac
xclip -sel c -target UTF8_STRING -out |
if [[ ! "$out" == "redactle-$today.txt" ]]; then
sed '/^https:/d;/\.com/d;$a\'
else
cat
fi > $out
echo -e "\033[\r2KStored $out"
fi
done
echo "Collection completed"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment