Last active
January 27, 2025 09:29
-
-
Save isoraqathedh/d93b1d90485784fab62b5e9e2ff34b75 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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