damastodon.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #!/usr/bin/python3
  2. from mastodon import Mastodon
  3. import draughts_engine as dama
  4. import login
  5. import pickle
  6. import random
  7. import os
  8. import time
  9. import sys
  10. import re
  11. #configuration server
  12. api_url = sys.argv[1]
  13. save_position = "/tmp/"
  14. CLEANR = re.compile('<.*?>')
  15. botname = "@damastodon "
  16. #board appearence
  17. frstrow = "🇻1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣\n"
  18. column = "🇦🇧🇨🇩🇪🇫🇬🇭"
  19. space="🟥 "
  20. white_norm="◽ "
  21. white_knight="⚪ "
  22. black_norm="◾ "
  23. black_knight="⚫ "
  24. empty="🟦 "
  25. def cleanHTML(raw):
  26. cleanText = re.sub(CLEANR, '',raw)
  27. return cleanText
  28. def check_message(notification):
  29. account = notification["account"]["acct"]
  30. try:
  31. content = cleanHTML(notification["status"]["content"])
  32. except KeyError:
  33. return
  34. content = content[len(botname):]
  35. saves = os.listdir(save_position)
  36. if "help" in content.lower(): #Ask for help
  37. mastodon.status_post("Hello @"+account+" \nchallenge an user by writing to me\nCHALL <USERNAME>\nEx. \"CHALL @someone@mastdn.inst.wxyz\"\nThe challenger takes WHITE and begins the match.\nFor movements and jumps, write the coords separated by spaces.\nEx. \"A4 B5\" (normal movement) or \"A4 C6 D8\" (double jump)\nQUIT ends the match.\nCommands are NOT case sensitive.",visibility="direct")
  38. return
  39. if not os.path.exists(save_position+account): #If there is no a savegame file, then lobby mode is activated
  40. try:
  41. challenged = notification["status"]["mentions"][1]["acct"] #If there isn't another account cited, then the request is malformed
  42. except:
  43. mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct")
  44. return
  45. if content[:5].lower() == "chall": #Challenge someone, check if a savegame is already existing
  46. file_save_white = [sv for sv in saves if account in sv]
  47. file_save_black = [sv for sv in saves if challenged in sv]
  48. if len(file_save_white) > 0: #We are playing a match
  49. mastodon.status_post("Hello @"+account+" \n you're already playing a match",visibility="direct")
  50. return
  51. elif len(file_save_black) > 0: #Our opponent is already playing with someone
  52. mastodon.status_post("Hello @"+account+" \n the user you challenged is already playing a match",visibility="direct")
  53. return
  54. else:
  55. with open(save_position+account,"wb") as f: #The request is valid, writes a savegame with the first element as False, that marks that the game isn't started yet
  56. pickle.dump("WAIT",f)
  57. ident = mastodon.status_post("Hello @"+challenged+" \n@"+account+" challenged you to a match of draughts! Answer \n@"+account+" OK\n to accept the chellenge or \n@"+account+" NO\n to cancel.",visibility="direct")
  58. return
  59. elif content.split(" ")[1].lower() == "ok": #The opponent accepted the match
  60. try:
  61. challenger = notification["status"]["mentions"][1]["acct"]
  62. except:
  63. mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct") #Somehow, the opponent answered with only one account
  64. return
  65. try:
  66. with open(save_position+challenger,"rb") as f:
  67. start = pickle.load(f)
  68. except FileNotFoundError:
  69. mastodon.status_post("Hello @"+account+" \n unfortunately, your savegame is corrupted or missing",visibility="direct") #The file has moved or corrupted
  70. return
  71. if start != "WAIT":
  72. mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct") #The user that challenged us is playing a game with someone else
  73. return
  74. os.symlink(save_position+challenger,save_position+account) #Linked the two savegames together
  75. board = dama.init_board()
  76. with open(save_position+account,"wb") as f:
  77. pickle.dump("START",f) #Now the game has started
  78. pickle.dump("@"+account,f)
  79. pickle.dump("@"+challenger,f)
  80. pickle.dump(False,f)
  81. pickle.dump(board,f)
  82. mastodon.status_post("◾: @"+account+" ◽: @"+challenger+" \nturn ◽\n"+dama.draw_checkerboard(board,space,white_norm,white_knight,black_norm,black_knight,empty,column,frstrow),visibility="direct")
  83. return
  84. elif content.split(" ")[1].lower() == "no": #The opponent refused the game
  85. try:
  86. challenger = notification["status"]["mentions"][1]["acct"]
  87. except:
  88. mastodon.status_post("Hello @"+account+" \n your request is not valid",visibility="direct") #Only one user in the message
  89. return
  90. os.remove(save_position+challenger)
  91. mastodon.status_post("@"+account+" you cancelled the challenge from @"+challenger,visibility="direct") #Game is cancelled, free to challenge someone else
  92. return
  93. else:
  94. mastodon.status_post("Hello @"+account+" \nI can't understand your command or you're not in a match.\nWrite HELP to see the list of available commands.",visibility="direct") #Every other command for the lobby ends here
  95. return
  96. else: #We are in a game, so movements are parsed and lobby commands are disabled
  97. with open(save_position+account,"rb") as f:
  98. start = pickle.load(f)
  99. if start: #The game is started, load other parameters
  100. black = pickle.load(f)
  101. white = pickle.load(f)
  102. turn = pickle.load(f)
  103. board = pickle.load(f)
  104. if (start == "WAIT"): #The game is not started yet
  105. if "quit" in content.lower(): #Game withdrawn
  106. os.remove(save_position+account)
  107. mastodon.status_post("Hello @"+account+" \nthe challenge has been withdrawn.",visibility="direct")
  108. else: #Lobby is disabled if a challenge request is active
  109. mastodon.status_post("Hello @"+account+" \nyou have already challenged someone, type QUIT to withdraw,",visibility="direct")
  110. return
  111. if "quit" in content.lower(): #The game is quitted
  112. os.remove(save_position+black[1:])
  113. os.remove(save_position+white[1:])
  114. mastodon.status_post(black+" "+white+" the match was cancelled.",visibility="direct")
  115. return
  116. if (black == "@"+account and turn == 1) or (white == "@"+account and turn == 0): #Check if the turn is right
  117. board = dama.valid_move(content.lower(),turn,board,inversion=True) #Function dama.valid_move parses the input for couples of letter and number
  118. if board == -1: #We made an invalid move
  119. mastodon.status_post("@"+account+" \nInvalid move.",visibility="direct")
  120. return
  121. else:
  122. with open(save_position+account,"wb") as f: #Save the updated board
  123. pickle.dump("START",f)
  124. turn = not turn
  125. pickle.dump(black,f)
  126. pickle.dump(white,f)
  127. pickle.dump(turn,f)
  128. pickle.dump(board,f)
  129. if turn == 0:
  130. colour = "◽"
  131. else:
  132. colour = "◾"
  133. winner = dama.checkWin(board) #Check for winner
  134. if winner == (False,False): #No one is winning yet
  135. mastodon.status_post("◾: "+black+" ◽: "+white+" \nturn "+colour+"\n"+dama.draw_checkerboard(board,space,white_norm,white_knight,black_norm,black_knight,empty,column,frstrow),visibility="direct")
  136. return
  137. else: #Someone won
  138. if winner == (True,False):
  139. winner_t = "WHITE"
  140. else:
  141. winner_t = "BLACK"
  142. os.remove(save_position+black[1:])
  143. os.remove(save_position+white[1:])
  144. mastodon.status_post("◾: "+black+" ◽: "+white+"\n"+winner_t+" WINS!\n"+dama.draw_checkerboard(board,space,white_norm,white_knight,black_norm,black_knight,empty,column,frstrow),visibility="direct")
  145. return
  146. else: #We moved in a wrong turn
  147. mastodon.status_post("@"+account+" \nIt's not your turn.",visibility="direct")
  148. return
  149. if __name__ == "__main__":
  150. if api_url[:4] != "http":
  151. print("Invalid address.")
  152. quit()
  153. mastodon = login.login(api_url)
  154. while True:
  155. time.sleep(10)
  156. for x in mastodon.notifications():
  157. check_message(x)
  158. mastodon.notifications_dismiss(x["id"])