Automating playing on lichess
Lichess let’s you create a token at https://lichess.org/account/oauth/token/create which can let you
get positions and send moves (plus much more!)
This script I wrote abuses it to cheat at chess
I found it works for rapid and classical but not blitz/bullet chess.
import requests
from json import loads
from stockfish import Stockfish
from os import system
stockfish = Stockfish(path="/usr/bin/stockfish")
s = requests.Session()
lichess_api_key = "..."
cookie = "lila2=..."
def new_game():
print("new game")
s.post('https://lichess.org/setup/hook/XXXXXXXXXXXX', json={"variant":"1", "mode":"1", "timeMode":"1", "time":"10", "increment":"0", "days":"2", "days_range":"2", "color":"random"}, headers={'cookie': cookie})
opened_in_firefox = []
while True:
req = s.get("https://lichess.org/api/account/playing", headers={"Authorization": f"Bearer {lichess_api_key}", "Content-Type": "application/json"})
nowPlaying = loads(req.text)["nowPlaying"]
waiting_for_everyone = True
for data in nowPlaying:
if not data["isMyTurn"]:
print("still their turn")
continue
waiting_for_everyone = False
stockfish.set_fen_position(data["fen"])
move = stockfish.get_best_move_time(300)
print(move)
game = data["gameId"]
if game not in opened_in_firefox:
opened_in_firefox.append(game)
system(f"firefox https://lichess.org/{game}")
s.post(f"https://lichess.org/api/board/game/{game}/move/{move}", headers={"Authorization": f"Bearer {lichess_api_key}"})
if waiting_for_everyone:
new_game()
Puzzles:
import requests
from json import loads
from pynput.mouse import Button, Controller
from time import sleep
mouse = Controller()
s = requests.Session()
lichess_api_key = "..."
cookie = "lila2=..."
def click():
mouse.press(Button.left)
mouse.release(Button.left)
sleep(0.3)
def refresh():
mouse.position = (121, 116)
click()
sleep(1.5)
def move(solution, turn):
width = 96
bottomleft_x = 600
bottomleft_y = 920
map_black_letters = {'h': 0, 'g': 1, 'f': 2, 'e': 3, 'd': 4, 'c': 5, 'b': 6, 'a': 7}
map_black_numbers = {'8': 0, '7': 1, '6': 2, '5': 3, '4': 4, '3': 5, '2': 6, '1': 7}
map_white_letters = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'g': 6, 'h': 7}
map_white_numbers = {'1': 0, '2': 1, '3': 2, '4': 3, '5': 4, '6': 5, '7': 6, '8': 7}
if turn == "black":
for move in solution:
mouse.position = (bottomleft_x + width * map_black_letters[move[0]], bottomleft_y - width * map_black_numbers[move[1]])
click()
mouse.position = (bottomleft_x + width * map_black_letters[move[2]], bottomleft_y - width * map_black_numbers[move[3]])
click()
if move[3] == '1':
click()
mouse.press(Button.left)
mouse.release(Button.left)
if turn == "white":
for move in solution:
mouse.position = (bottomleft_x + width * map_white_letters[move[0]], bottomleft_y - width * map_white_numbers[move[1]])
click()
mouse.position = (bottomleft_x + width * map_white_letters[move[2]], bottomleft_y - width * map_white_numbers[move[3]])
click()
if move[3] == '8':
click()
mouse.press(Button.left)
mouse.release(Button.left)
def main():
req = s.get('https://lichess.org/training', headers={'Accept-Encoding': 'br', 'cookie': cookie})
line = req.content.decode().split("\n")[0]
id = line.split("Chess tactic #")[1][:5]
print(f"{id = }")
turn = line.split("Find the best move for ")[1][:5]
print(f"{turn = }")
req = s.get(f"https://lichess.org/api/puzzle/{id}", headers={"Authorization": f"Bearer {lichess_api_key}", "Content-Type": "application/json"})
moves = loads(req.text)['puzzle']['solution']
solution = []
for i in range(0, len(moves), 2):
solution.append(moves[i])
print(f"{solution = }")
move(solution, turn)
#req = s.post(f'https://lichess.org/training/complete/mix/{id}', json={'win': 'true', 'rated': 'true'}, headers={'cookie': cookie})
#print(req.status_code)
if __name__ == "__main__":
sleep(3)
while True:
refresh()
main()
Bullet
import requests
from json import loads
from pynput.mouse import Button, Controller
from time import sleep
from stockfish import Stockfish
mouse = Controller()
s = requests.Session()
stockfish = Stockfish(path="/home/connor/Downloads/stockfish_15.1_linux_x64/stockfish-ubuntu-20.04-x86-64")
lichess_api_key = "lip_yWkxKrk9vvJ1jCKykQnL"
cookie = "lila2=9623260e2d0cc0c2ff9a3bda45634e0523aba1c8-sid=HPOB5sZEHSG9RBx2v6xLI2&sessionId=i5ln55mmA7CV1hj1qqxk7e"
def click():
mouse.press(Button.left)
mouse.release(Button.left)
def play_move(move, turn):
width = 96
bottomleft_x = 600
bottomleft_y = 920
map_black_letters = {'h': 0, 'g': 1, 'f': 2, 'e': 3, 'd': 4, 'c': 5, 'b': 6, 'a': 7}
map_black_numbers = {'8': 0, '7': 1, '6': 2, '5': 3, '4': 4, '3': 5, '2': 6, '1': 7}
map_white_letters = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'g': 6, 'h': 7}
map_white_numbers = {'1': 0, '2': 1, '3': 2, '4': 3, '5': 4, '6': 5, '7': 6, '8': 7}
if turn == "black":
mouse.position = (bottomleft_x + width * map_black_letters[move[0]], bottomleft_y - width * map_black_numbers[move[1]])
click()
mouse.position = (bottomleft_x + width * map_black_letters[move[2]], bottomleft_y - width * map_black_numbers[move[3]])
click()
if move[3] == '1':
click()
mouse.press(Button.left)
mouse.release(Button.left)
if turn == "white":
mouse.position = (bottomleft_x + width * map_white_letters[move[0]], bottomleft_y - width * map_white_numbers[move[1]])
click()
mouse.position = (bottomleft_x + width * map_white_letters[move[2]], bottomleft_y - width * map_white_numbers[move[3]])
click()
if move[3] == '8':
click()
mouse.press(Button.left)
mouse.release(Button.left)
def main():
while True:
req = s.get("https://lichess.org/api/account/playing", headers={"Authorization": f"Bearer {lichess_api_key}", "Content-Type": "application/json"})
nowPlaying = loads(req.text)["nowPlaying"]
data = nowPlaying[0]
turn = data["color"]
if not data["isMyTurn"]:
print("still their turn")
continue
stockfish.set_fen_position(data["fen"])
move = stockfish.get_best_move_time(10)
play_move(move, turn)
if __name__ == "__main__":
sleep(3)
main()