FEAT: added Wordle

REF: Requirements.txt got updated since we added an encrypted wordlist
This commit is contained in:
Dan 2024-07-05 17:19:28 -04:00
parent 0914cb30cc
commit 2674955d5c
6 changed files with 316 additions and 0 deletions

View File

@ -25,6 +25,7 @@ config = {
'data_privacy': {'enabled': True},
'terms_privacy': {'enabled': True},
'knucklebones': {'enabled': True},
'wordle': {'enabled': True},
'profiles': {'enabled': True}
}
}

View File

@ -0,0 +1,142 @@
gAAAAABmiGBez3P25GGn0jWx1deDsb1oIpEV7IU4ZVgOOL24S5r6WfidvQ6g4Yrq84E9gQTSkdcwn_lnm_2zpjSbe9X_qhontQ==
gAAAAABmiGBejvP841lVXZ3ZCA_95MlnRk3UMtJCnzCFMa3QSN5ViaSg4UD3SSqQq9gIE-fc1GL8Gb6m8iOEqhxfmR5HeNyu1Q==
gAAAAABmiGBeRhhg4lJY8Wyz0fUkmZELYKr_twUFba2ZbxoUTKGGGdVUt7yrkG4-UQxqg-IP4ufHZUu-k4w-mJ2gWA25sKrp9A==
gAAAAABmiGBevngRUaVoomllodc0IpcvKWhm-AjzNUaTpjyns_rh5DHbYuWTj5pgUjJXERZEhDa1BrQ3OqLAk2wayONLNnH3eQ==
gAAAAABmiGBeUp0Wyr0XNACS_tY_55WTFf84Jdmg2JCTR9_9bkAfhqZv22PTSN-xdxz9VADh264BDucz2YRoHOVmdbqXMoz0eQ==
gAAAAABmiGBe5vAqONV8OfOznlcLYMh9KcyPxI8IcyIOUDdxSmMOoxDVGpxRPwyowJDokgzZGmq6tvXLlnBcwbWleoECopUO-Q==
gAAAAABmiGBeAXmUWejjs0rIvDlVsx-U3d2MdS_rjNLbSgq6-ukcuFhDbr0nWIOD83DMcO2CjAGJWN-a2Mw8Vdql287v7M_AEA==
gAAAAABmiGBeA1jW_FbcAo3JDFC9iX2abGFIR7EW8MOH5zcWfZMhPCGnsvbu69fZP35SudeqbMNhLy7drASV-Z4KtXnwyZD7qQ==
gAAAAABmiGBeYf819SSXTwW_9MbUtfE8xAjtqHkFCbXY7Vgma36Tchl6LqV62jlodDqvHhbQ-fStSEsjG2bPdO5OI3_PmCb3TA==
gAAAAABmiGBeztzZr4I-jyrB76dZjjDkvK5b5kaY06Vol6lGjoqz10qzIWBkbpvmvvdAT31Q01vPyN4iU8vpWNSNTPkV1vlfAg==
gAAAAABmiGBekhbLv-48kdCUF6j4hU2JrTXnu5hnezTz2UEXqD15PZeDITuyRUqa7hNbo3FkBzqGYQsXz4gDi_f-0ViYCsCQJQ==
gAAAAABmiGBeja_0vafWUUN87JOvFh-aQci_XzIqTrCqr629Y_xHO9cBvrSa0tmK_DHMcGISN_Ls8iVFOWt1U82sTy2DiDU-pw==
gAAAAABmiGBeR9ovJk2ONg0Pee3LXsJQoj5ddXdGIln9yakJ4ZztJUmjHMjFKU1S8tZb_xpHEHp6pbG10RFqk1yRRR-T5Y_WVg==
gAAAAABmiGBegcizm8mJR5V7yHpp7Xp0Fs0uC2mxf-4NzeIyQK_zEmPOOHQj8s8htTdk-x-fUwSD9qpFSJt11zSHdyONRkHvDw==
gAAAAABmiGBeJIUMxf6HdcWpsLLeKEJDwt6QwbC709xUEPdfmQVAA1N7Nl78MtJqSJxQ9bJC7wcJgg87IRC0koqViN3M1YWjKQ==
gAAAAABmiGBeL9xj9HLcmegi45KteAbupTac77kfC484qPi7MJA_xHMcHGY-YOrIFEo37Xb7w7aivNt9YaVOi5IkVNan1OnVFw==
gAAAAABmiGBe87S8w710hzzQlEdplEsJxAygJb9ZBvcd8_9l3IMzWLoI9lwJrlZtbG9a1mpO37EbTLcKdN0trhqZCtnItsWa2g==
gAAAAABmiGBetXiT4f2aeTQmpibgYQtgreQC3mDYuTqYFcuz5Im_b9EF3X4cP6Xg_TWNzz1x4GtduktHrRZ169Ro8CvBxcuWfQ==
gAAAAABmiGBeVIXUxhIGbdpqjiJ5pcZ2mbbr_YaG0M98u9iysVJqxsgTKtxhrI8BDux2PxF71vHS9VY7aiM27UMXBnoQTJqniA==
gAAAAABmiGBeFZ_eKtFb9anrmyns5cMMDfvhH6ZeIjUUt2QDgZLBRhE_ObgyWXFj4MSk32hl60p4ZkBzd9TivlUv6pfZmN0HUw==
gAAAAABmiGBeGltFO5nGfyvZB48Y86Jb2RTJEUWlYe_0uAkAeqagJhQkM0L41Wa5ipFhtdhvaYUzIw2WEWcpPMh4Rbrc4k-Ugg==
gAAAAABmiGBetjFqcCEB-85G3iMm_ITyZH78ECDtWvgEzFHsfWeKkt2LW5dhw1NCG-_A4xkrUbtp98X9_-AHwOOVDA_Qnvgt0Q==
gAAAAABmiGBeA22zlQbVE_cFLQIaFKR_Dd01G2Y9MG1zM1iP_W2YEYS5kCeV4FmR2w--0tdajPxljhQnZoFSqh-xAkR8SfhGvg==
gAAAAABmiGBezdUKsSIPdOruL-MByI4F3vXvEHLQHauzifJnqXIrAlo_8uoICLOb8lH2tXBe2oMfVGTXuCt4v2v8cvLfyJCvtg==
gAAAAABmiGBeXCtGzc-NksPzpLZHGXkY9mgQb_jVu8rW-jR8NZrvESY5HpkRb49RdmOloo4npmvc2IqdPJLhnMtUYWl4x-MciQ==
gAAAAABmiGBe3Ly8SPsWI-kQyWKouMHRlyqJP8j9GlW5eHZlZxaB0uz1WLJgfqG0hXebQZmVwLZRKRMbn7-hNDXhAIxuyf6rqA==
gAAAAABmiGBeVUxmJrqpAA0yEwRUrFnZuPv-aZRO33xkDZ3LHK7jTaUbG-7GWEduFnth0O65Y7xpx20ehxeWWeHg9B18eeZLEA==
gAAAAABmiGBebS6ZFcceVeM1FdE1DcykOAHrH6q6lK9jQ8Ys3na2VwwymC8ut6muZgWYVjRuposve-62LJlpZ7G4rm1czdtDsQ==
gAAAAABmiGBek_OcTkRg3v5xwKvx_-FSBTHGFkzBrGVw1RQAR8AekT5aluuyroxP46uVGlnH-8fSsCNDTIZ7A45EwMIpLt-5JQ==
gAAAAABmiGBedkkvrywKcZv9ncnXDzkjLlt02Dj9cn1_pxcZLub0oWlsuQS2gqGyZlaW3TySBK40FJhWEYGFrGxz0eOXG4kocQ==
gAAAAABmiGBe4kaJLtMhIVtkzXkLFkWeQI1fEoJ4fNJCQas9xnEi-n672yrrS8wr7ZJd193gTp6t7FOhrrIM6KlnXCax0PBXXQ==
gAAAAABmiGBeO8kOd-oG3AJ-hRBM3xYHI-paZGLzHlPUFnAWl3iftg0hLvbDEACyn32JwLH-53FEIV5D3IDw88XubwCMboHAzw==
gAAAAABmiGBe9QPlqsPdu-FtddreMB0L19_frNSz0qWKuelo9Gv5rheGpBSuOI7iKFrBXQFziZJQpF9LrzYBHNAsqzPEOqxvEg==
gAAAAABmiGBeP5LsqXg_NFMY7vzs0aGsVK9n5Nay_i_E_ym6hD4KG_bix4u39AqUjb9Xqo-coHgCaKui8V9oCFVXEMIFxxnz3A==
gAAAAABmiGBexoCMcMLDoVJkHzcld4iUE2Tw8SO97GYkrDsf3Nv5mWyuiP4tvfBLDvok1Prz7IDcNu6ioy_IP0v4169THgh0kA==
gAAAAABmiGBetT6P2YhqftrXd8qawxZejTP20_L5IB0MI_gFhCO0dZt_GBZDV0L-45ob60QiVuXAQFDjFT5a7QOPVH8Q5eiyUQ==
gAAAAABmiGBeyxX-J0HZpxGfWxIvBhBNCRdeVdRwc_idW-p4qaejNJRNfkCMvZ-V5ou0bslAuWJu51iQJgMmnfGrWdmgWenPxA==
gAAAAABmiGBeXyiN7FNM5ol6WlQCz8aCwFN5mkY37u9mgX1nt3tlYtht9lovrcBOSQxytOCHjk2TQowrKqyUitu0VK-Byq0p6w==
gAAAAABmiGBeTqYfz3oXMKzLMETkmA-Ua8IcliNFih8TtsfQUiaqyiTWUzmiqJMRVbp_DNWwCs1QVWB5E9xNu_OpdJPZ3xCSvg==
gAAAAABmiGBe8Gdq0EE1p5StrJFxLunocKPcGKV-CJknJ0vOeG8Ma5eJTLhuIMxYxbBzochyJUY9Awipl5C8yU9bY9fjgVIVXA==
gAAAAABmiGBe-GdlZxJalBfeRTRsk2QEKNrom9s4vkn0cX2OpDc3O9vWQ4sZsF-prQzLJpd-_QucJz87wYloPOkDcCyIlUfghQ==
gAAAAABmiGBeJM-M6EdiJFP_tGFFT2Jfi1gAn6zzi81sIMPo94EuVg3MacLdi7M1jMSSeXigmTcZJffP0cHZrmAWKiY73v_--Q==
gAAAAABmiGBe439eGaTd-xNK242LyNdpCb62lh4ycdwkCORZX3C6-Gc48Gav31eh1r4-SH2b5R5ianSSWHeXZTn8GkK9JXPlbw==
gAAAAABmiGBeYR2bhkF5E_JQ2aP64S9Rk3MLUop5l7ePI2KQg55tRZzd45HuwwedvfSbQ6bQnE8YGMbL9F6H_s84Ad2XzBqraw==
gAAAAABmiGBemMMKI3IxikqSbq0PC2mcTnhDWMkYaq8BTxoFPZvcuIviqkXax94vNBnmvW2cb1i8TyWNEjuri_zYBLK9RmdBBQ==
gAAAAABmiGBehBFXbc5a4ZGmVf2QSWmjt9d46sk8MRLwDEW0XZGsBpBhqXFsd-OI4cKcvhIIq_3ekLhVbykueQq6zwhPbL2mxw==
gAAAAABmiGBeqw2AIQ-va8eclQqvMTDOFQrcfvab7zr-KLyDJ3QDt4NUeqZsvS8Sb-nOxjvcSoSxYs6yOlBi6KjMnggmJIjA5Q==
gAAAAABmiGBexrW0Y8F12ZOv_Q36tye3jHauY8ZEdivO-PthNOwbGdsH9hDmUHWbfJNzJjHzL2kcJrKgupY88R9WEjGXn8ZBuw==
gAAAAABmiGBemR2jD_liGj5LcKczsKQi-0uuMmOnWIih0-7umAZoYy3Nzl13FC-Nd0Gj6c4ElqO3dNGl7soM1VqNWXvNxLpwdQ==
gAAAAABmiGBePuRqnyLDCnZTqPBMrDbqRneWhtxZAVqd4npd9bIMv_7KSFq1k_nZG_S3wT11NiWbQUqmucxOvWlblFmYxHpxcQ==
gAAAAABmiGBe9EnAWtWzYrhM1Wqwz2BiijQ07PC8qOHUL5CZkpz4akFl0gb7r9Y-i6v_uuIAg9BATG-rnNSeQtRfYAhVv9qLBw==
gAAAAABmiGBeE0yy6A1e4tYMp2Dz8RbRPKJ3iDt5n-PgzPcMQz63anVMgJmbNXcxvdCn7eKFAJw-qMRhvBtgF_MEkpGnz66l-A==
gAAAAABmiGBexBqB8-W-TStm_-Eb45Tj1tmtwACtdImH9fuffUUePUvYpyK7DynmSLK6s4Hcl27O2muCEp_bPvSPFy0Tb9bpzA==
gAAAAABmiGBeM_fbbOguy8O4iYH6ktnkLp82ZyV9B4lZILhf5QHC4n6g5Ah81cCKPjoHSRqgm77DUAu7EI78fs9YIHL9XHiFtg==
gAAAAABmiGBe9JwFSkg6QhnwWcH1YrN8dnMYg53Z90B_VI91KAA4jmeqZCAUvtxmYvCeFMUuJ350XCqv4wcj_BtJ3SKuPceL-w==
gAAAAABmiGBeIsuGLeD0D2hL5HwWYANwpRzr-IYIE2oRajniXrpf8qZyhI91mlhkXlDLjeFr0TxzXgFwy9EOheXbOvGL3Xs_Dg==
gAAAAABmiGBevIc9u4DzZc-gCqXX0f4EJXBMVYzBg69Q0bxEWKyAzkpdTCHqTypJ7nE5EKGXqfUhXsQYWacrdcRWkBmc3ZD6_w==
gAAAAABmiGBeBuJ6KHF1qrF05mnpd77lwL4tmmk6FR3ahXTdZuiHr7xhCccjiFDTffvfHJZc-2ccFm0Kdas5AVKGkDWI4L9bXw==
gAAAAABmiGBeaj50_Ea0jqe-E5kz1T2ywI2UJ__pcMkA5ggEmMtV_X_g1zIL_MVLkHaNPuBbCS5zUErusOQziazQYO51lC9zSw==
gAAAAABmiGBeJ8zpbvRNQMSha8XovkGg4O7Nh1BrtzvuPDrU4j3g9OfrIRRZY6gs9B5Y7X3snvYOFUhv69Vvo5SxtK-eN3n1ug==
gAAAAABmiGBega5Bct8hU5YwFaV-sln_C0Nkqk874oeExWvLOA63bHUS-fMWaYf20KssRlR5F43QVCV8p37QMOzAW2SBzTEgVw==
gAAAAABmiGBeKh6N_zSAYIjlMi0sYPiaeiLOTMLlE4VdDCVYiaNiA9tW5gdnVkXJRS7bEGf-EFQ86qed0B_lAixe-Q30kEyDsw==
gAAAAABmiGBeOLbCos9_j0Vd9TIaK-f4YZch5yxafMWWKyuHTH3tLT3oqac9n4khN1AVs-Osusv5EVrYl3l4C7TVHFoAeqANWg==
gAAAAABmiGBedjUiInJnLly6cylrkP2HlRA2vj6VboTeucpZ_U9sFtygbee5oglUGS66x8hj2FW7qDWA9UZty--aOKP3LixWng==
gAAAAABmiGBe1XwlvfvBn9eM9zXfHD-vlTblMIRvDkFSizj-pYh9cU_-672zFjr_zdLPYo0K9bB0k8-Lz9fwf3liiYhLx1OTnA==
gAAAAABmiGBe9oO3mQhwHiTQAep6U5DLQULXoD1KLg0fMWc1z7iaXQ_87RcUZ9Vg10IgA7CR5aVRXFmwugOi2ROO4Umj59bt9Q==
gAAAAABmiGBemOYRBnd9PaLchxYZehMr__NL4WMG7c8dTiWxCQBWTUXsPBYVkR-pthLGXySVNK5JWa_ECPSoUk4Su0yOuuGAHg==
gAAAAABmiGBeJs7d4P240rE71BVNsOCJQMM5nnw9u5CP2t6wh3mq79W0xsj0SDQS0OWvmJaPo9JWD53dp_2vkF5uBx0IWhQr7Q==
gAAAAABmiGBekT7VZL9zsgvDyYqM4gMfvLGBvhi7tTIojtD7Sf0crCh4A1y-VMqHPkt-lhrXnt0-z97zbPj4YzyTehVrJbTOdA==
gAAAAABmiGBeXuC2QEOzaY6Rh4UPKdU5Uai4rgJPdJxwecWnzjMyQ75DzZFZnR63fRJzZDzEX0MDB2X0qnMc0P_6poPcS4CgdA==
gAAAAABmiGBehbwKXfjeBurCrBGAW-pFLJvAIjcjR4uFs3XUsxz94FgSRhcP3EM3wF0L8UF9BaKjxxqmDgF0XaH7dJG1LEx_AA==
gAAAAABmiGBeHTV3hklgTW2zdzuUIhhptx5hFFQkOuSJGDDFrqa-EvQM9m85QOtvdaapAZ7T9VDBugZk5OGM_MQr3PgH1uxtoA==
gAAAAABmiGBekcytpYfddImZACFJ2Gdmodr1JBQ5-hWAQwfpHMe0p0kdnoulEZh_BtWiV43qBomFfo13Xi6YPt-57jpoS_fXXQ==
gAAAAABmiGBe9DeqZFC2ImX4vpBuoA43oftxH3372G98Na9V0u0q-Rfmmfvkf3S8osgBfwQmPQh_VkTASttBlYgZR19A_ijJVQ==
gAAAAABmiGBe12el2Q7LMDwXDiSv-1zEaWJurFTIm511H7fXVmPR5q8H_wJjHdDxYv2x8N3JsalGuh7g4_OQZVntQVuZRt9Dgg==
gAAAAABmiGBexaQmgCKkVpP4oeZbGgBwz-4QdbR9VpIg2rMbDMlxxgD1s61Ps8bUGFb9CSy0fKaN7YOZfsfVc5kWmKAXM-ZQrg==
gAAAAABmiGBeIShjv9ZgAMXJzEIgZG_k0E4P63HB4OosbAEXnsZglYp3BL6Lfp_gsCvDOibipowoLE9bRLDCM9a6bnS1FHPe-w==
gAAAAABmiGBemNkvc_zd-Ignvo0hbp65JWctJTae0yxRe-jTGAnFfEHuf3ne3GrDijyjE6yOYShdu0HJwiFZ7SGwN6RnzEQLSg==
gAAAAABmiGBe_m93N4cuKOfYjH_FEsjeD0WEsRIzfe16r_w0pi2M1dYzfkJlfu-QCSfZA4CllE5rsgMS4AK-wXEvRD3c9aa60Q==
gAAAAABmiGBea7Z0Mn4HoT0u0jdzcfsi-ZSuLqvuvsQGokkHrFN9xTKUOGKy3mt56PigeDW3QO9v7kXX-piZMxbB7-3lZjR12A==
gAAAAABmiGBeUc86QwIoOQior8bSDbqq5bOcldHwM42_Mn1kylO9tWwTsTD5Vyb9KbT-LMlwXVs_JdzERE-QPSr9NOk63kcGfw==
gAAAAABmiGBey4wXPm_zRlPJMko6DZFbf0prCGhT8ZlPtvOJ_OqWRbWRdi9su3uBF-DKB2xqnA2CYXuRQLedb3GcoRlM9FmRug==
gAAAAABmiGBeNEbOmK0ZjCRn1lKViedDxY1DLQue9dMshgO3w6N-MHIHJqSeSby5XMIl52hM1PF2EeiIU-oCytoKJnmysvEMUA==
gAAAAABmiGBebsZIk75_eNbPhtgEyqWUQqozxZzOLtEx4rY_Ts6x8Hy6OXWpwQTfDaHMgGvzI0zjG7JD5D8xkwEGk9TrbILbGg==
gAAAAABmiGBed3P9LP2XUyQmMqOsfgd1aTdpqQfvSOZGO_rnKqidO79HdRHWHcqCbKXLv8asOvwKYtCTFGhkKOce64eBVDiowg==
gAAAAABmiGBexl4iai6_Le3Scd84J7nv4iGCCaXPSTAugbA5ReGNqbaWBt5iqeRJt2wKns76dCFvygSdVr48erFCP1GtJfzefg==
gAAAAABmiGBeHbOUjc0VBNxxaWVnPnfwQl4tYosP4ZadVRCU3pTofOQrRDl4Yw8blCZGDZC5N7_mu4SMQ9PqyC7jrE3mF8B00A==
gAAAAABmiGBendqbvTJ6PMRvFxwLyoOQNrdaAz3GQzPAUFFlpe3XVofMP6SCR143NR60dms6XGuBAI6NfXFsE-9ApI_rLz007w==
gAAAAABmiGBej6aGyN5xZ7HMiQ166J2UVM4dWxNg9ZNdaGcE9if0QO-EO_4PQ47oHPhcev9YAfsFs7nGrtB4lDmnRxgTFykXlg==
gAAAAABmiGBe9mwN-NwDVLWwCHR4Pk6sKvLssrs8eMCWdLumKmsgs8HpYkTI1pdxf-T_WFMKEVWOSa80_i7_C3TCdBAeGqXINw==
gAAAAABmiGBeKdG87FUw9nCDno_LzkYE1_npOPsKr-GnOKw9Wl6FFTAPHUi_UforcPRy3c9jZ9GsukkMLTSBrlQ-2qWPMriihA==
gAAAAABmiGBe_YC7bNDSAM2VShglash712cXq0gyLI_SOCmL8GmsGsN6htksjutOKrWko51f_rPiPquwWCLPiZMy1TBYM_o3wA==
gAAAAABmiGBeux4zYQaVPwSukoXiZ306ctICDzFy6TrswbpJ_eoM5RsmC8rLb1uSS6BqHfB2xvTQp86Alv3HFUjhqNhW7txX7A==
gAAAAABmiGBe8SRs2qtWFOzfg_fsxuzpMGcmynQBf5ewERp7RMaxh5dLMeNHzg_c1enoVO_B8yC9eABQgzhnNjhVur3OF7a-ag==
gAAAAABmiGBeRrBfV6UPNHvI16AAPQ5qD3TCXGZqN4hpeJOMffTuifSFoO2FnqD2sW1itDr9yYYbwAeg6D43XLadR0E5vGQ5rA==
gAAAAABmiGBezlGR-RIigHXyxIvh0LMqqRslQVkAT3zOhtd92Ic0_Sn4YJNpBT2iIOBealiYr9aLjLOXrupg-ctzgZxdYbxEYQ==
gAAAAABmiGBeok3ptnUxj4jT2iNN6pN1pHarHAFbYONJfq3dJXyNS-V04mpy-ASpETJhVqvd4yXqIMMIyOOMT7z5sOZTAfQCxg==
gAAAAABmiGBe4pIVucPnDujegjvAE6hSGwQmH5K5waTHsH4TT-Pzlgh3hZR7T-4bn6ZasPa49QazOjTGB1-LQpSWwjOQZzbIRg==
gAAAAABmiGBeRLJFrM1lpFPGSjmKgPFLvwYzWqHo7VOX4SBtmCj9vjSfUQ2YldwPUw9BU4NcKopX8fBglgbAt7mbQIZJJUzgGQ==
gAAAAABmiGBeyiwBCgCxOIX4jFoMtAVRpk4YiDvPDmym8Yt0wrY3xLBmOXoJpR38EUe050Ue_TuvXpCrv3rIqdSxyAGlcBT9xQ==
gAAAAABmiGBez4uDP-C7_eHS2FBCJcELHB2jmS0YdkBDcC-5yyv6qMLEGAvq5Fwu24Jl1Ses6GJ06rvIsaKPex-f9GR1Ok688g==
gAAAAABmiGBe2IhQNbEtzGThVQqDyYmLbSzYvjluDXEqDZ1cJ-W8W0FvDy8WYDcdOEckXA2qcaqgW891lVt1a-Ag9y-x9cOv9Q==
gAAAAABmiGBeNue5LnAzFuUJJqWpH9b3eDQ_-OHKzP9SRWBq1ziQnkRDZIczfMcgiUDC-FtEZd4KtKx2q1NUzmFMEMFGINxoew==
gAAAAABmiGBeRwxsQvki0wchQrFSiQYfx1EEWyeQRY1_QLve7SVrrTAHJNsDYc_Ukd3gYaOwHik8cDo1P3uW3QocveKhh4tqqw==
gAAAAABmiGBeYAt6Rm1sBhdjvVpbINFenM9ibxbJCt7G66Nuh4KOskYNqFj1rOmMFOgx2NJKnhST284E85sMaDyoPsY1X2KkDA==
gAAAAABmiGBer2fAvPOL8pvD_6qqtfxALjikN_Phz7z_QkKSn72N6i5giFgBz-8G7jWninRuKK8YarXVD63bSpmO6tUI3Fqvrg==
gAAAAABmiGBensdSs1E6eq1jvYJCTiuIn8fozM76xHnVZnSvOdjnodRR4mg9EcxThtb8msIjGYXQO3nBL65gNL3OhV4vPsvjbg==
gAAAAABmiGBeLToU73rGQEpBYuxGuR7qbKTV8cOkPocp6yuHL1a_e2tk5Ctm6AA2_QUklkZ44rk8-w5D4lrMvPB6p1F9TefRIg==
gAAAAABmiGBerm0abfRe96MpADs8SlNetoe2Tns3fbRvtsZ7-4_L549zmdjX3jpQgrg7Ky72366CTNJJRLFdYrBd1E50n0nT_g==
gAAAAABmiGBeGVZEll9cc03GgDn-lXdOdqtov1dNu4XeIaQCTWz4yV2FV00eg_nUzxRSpCnczly5KyVRX8lvOuc7p0V9jnnh5g==
gAAAAABmiGBel-7ZD14sHhTFcJJtixgmuR5LryvT_iTffEBNER2pjI8MTeu09WahuvD4XK0OXPgTAkgI2aYkg5Z0GtHeS3gZuw==
gAAAAABmiGBeAqockNltibw6NEWFfCZTpAObwthtoEXleSt5bTWp82MzpDQkeubvELY58vEjPXBPPAyciFdVClmGK_c_hF5cmQ==
gAAAAABmiGBeIg-HT8CHoUCK6DZQYNFQ8bDNcAkE1i0K1MBQJewgKBtiqMLmms_DQ6g9rPY1HOnC3chBzxaPNub696nEZgXmjg==
gAAAAABmiGBef4RIdvDHRkfc9rrm8Z-ca_IEqV1e5DSe7fL4ueMNt_D8XzXZRD0K96Q9mUCd3VDUH08n6rXviq-24CoKYjRdbA==
gAAAAABmiGBeIDs9L2Q0_fGbDyJaYchZD0ft32rgins-USDicuXUhHsULgc_ObD3atLOS3QCKnr30SNmWl6vFBjGr7TasrzHfw==
gAAAAABmiGBeKaVFgl44tcBwmeQO6C58EEj0OmiDfAhVLz4Lzqouo8bwPJT2TbxdNbnm5dyJVbreakpgVhXtsASFETkRNaRpvw==
gAAAAABmiGBeEFQsoQwYC-FgmPWCtUIytNXsvZ_pjGAzRsqqCzPnZwvXJ2LHmXD4XPNxgRjX8xPs2Hu6NZvVds2Y0c6zHUqltw==
gAAAAABmiGBeu_-GAe-GsS2NcvlT7kO0ObMgzJkvv8sKh7uZ4bMYiXG9COrs9WtpDxcEk3Dc_gwteOkmUjbH0hKXipEwmLi_EA==
gAAAAABmiGBewlW_6gVFFKi65HywAhJ7bl5EMbrlWxy_dtbZx-agn2aPJs9embZzEDBV-VGFo3t43nvOpirFkk8Epu1EmM9d5w==
gAAAAABmiGBedHCr6QdKngIVcMY3JNF5T-YRfDnvqoBOPAa2uM_Ra8hI0qdhJqMnWT4zPW-SbWXTzuvyk_HAlOfP4QHuvQ0DCA==
gAAAAABmiGBeAudgnlYElvlD4i77a-Nencbne2SV0MAPamLVGhjZJypXFV3Bp8qYkAf6drG1oK0lyRShYcIzIi5OHvcjF3YkIw==
gAAAAABmiGBejhSKOZUDpun9YcfN8RaGDuAs0bb5EnZ4hNx07cSVzMa0L4sa0Dr8sI_RkweMcqkyu5SpzOpHQz7pzSWU133KdQ==
gAAAAABmiGBekuxD8Um9QUlUJbDfDnD0LrdP2FDjhGYfzMA_bZk1B9zPiUSXWZ1MGYiGGifeZi1Bi05GLQVqd1RrKghaxGT67Q==
gAAAAABmiGBeVPBAOwK5atC0XcigtA1tDDlyYzB7t4jaH2EMcegy38tsIYvig4FXncne1Im6r4iuQ0xlqycp-3lvQ5TbC0ofuA==
gAAAAABmiGBehzZovJnfqU27lfXtkK0J_Mr58-HgMcv_jZIWX7MD4YulvoOcA0nMzFoC2AG9UNV35ioHAnJOyRhZeUxzeKc_mA==
gAAAAABmiGBe_MAXBrQrL4-8lwsCcQWBnLoOZhzvmPET8HenppfgPqMCjoA8iH9oelsxsRAKnuu531CsjuWAN3lrk3kML6AjQQ==
gAAAAABmiGBe7SclAu6-Ej_QKAqNI1j076rDrtTxyPoodvdUNc6wFkmiQMgB8Wnep-jh9USmVTNf3xLDtTkESWvaKi389LMz7g==
gAAAAABmiGBeAexOEyaxQkPfhio7Ku3hWrsUYtq3h10kzIgqNRFPe7Hf5qx5JwIP6Iw20oiRihGmpAbCrtj5DnH58yMUYyARDg==
gAAAAABmiGBeA01RT2Gv4wunnAdcEXgjEdGfPml8L1chMKVteh4ETLG__1vmMjlylRJd_duASyymcPAVRKGbliCdCT6bNsQNng==
gAAAAABmiGBeQwxwXIwe92jm_ti8E_Q-hneMkHXK0cyJTirp7DHEkEshkxM4HacICVaGRJ0teQ4BRCVmNrNLDTwP9KiAFSYtlg==
gAAAAABmiGBejTB8C55VArGvejJzipT6NT1c8DutiDICTlV1P8JAwiyz3T1IBlutirXL39d216ZcyMtUYxrpOxVEbk92N_WeWA==
gAAAAABmiGBeLtS8VgP_PIBqT2exmtET6jj_lhpdL-qzolFtJ3pWUEXR7WLfcXu9-vsXOnrwgYxXjHsFB_pFgAUkYOFWbgN5wQ==
gAAAAABmiGBe06x5AZsswb3e-gORZ4_I8wzL8IlI90hJylk-fs2IlBiKRqv0UI8RxvncQELiBcseTLTxpAwxeHb3tT75TcCqMA==
gAAAAABmiGBeT2ClmE02iROcOXC_YrQOya_2OZu04nIV0q4nLnUCtE1_QD88vudAUV4wqjKq211x0_moGz81yGhH0HUHzQOniw==
gAAAAABmiGBecAOu9n3rX7TAaoSvkNS24lxumeebT-92yH-TQLBScy2Qv--5MrhI8ohe5Az4okdY9NbQnYBI2nJDVU7l-2ccvw==
gAAAAABmiGBeBu1wJLSnvBhZDpS6iMEHC9oDjSyItY4NEuDzwOYyhVerY26fjXOuRtGED2_NXGRiD_t31QT8evNZOCC4cXXDqw==
gAAAAABmiGBekmNfazsSiK8pXdjbWttSd9IGiFc-VAAwP4p2AN_j8QkqoamZuUVzxP8VrVRDd8RI038xH5xTjUtv3fFWZocUxQ==
gAAAAABmiGBeVzEtbmNqI7CDg8K0A7aT9U3-9ly32_c-vHPdw_U5SFC_30DQ3huH3kf_D7jQCLDoFJzFTlSTBw_2-82MWemSlQ==
gAAAAABmiGBejbeqrR0FrkyQkpsU9pDw4expVHaTuE4VFOUbykMj3KIZ7SBx30BqffPMMZqAhwpuNbIHeVZpGr_0RgHpTrEBog==
gAAAAABmiGBeMw-OE-AS7nQDxEixUHu0he4WZ7W4Lp8iLYALiPEh5ELQnRHK9blGTkkQ3zljZcB8wBap8fF7CAFU9dH9LNpo2A==
gAAAAABmiGBebVn-mEieiBnk6-qHtMH3Zv85jPXG4zRUWhYEVMQLizHziBRW4gBYo_sEZUbfWrFKvydDASxyMIaDrHHRrZHQyw==
gAAAAABmiGBeIrd8LgnGqKHuVL7URqRa8bKgO1uTg4N8D7bZ7BxDMXN7pDTseka2qDtJ9TiChWE6_qtxYj8uNwa2ksTiZeLRxQ==

1
data/wordlist.key Normal file
View File

@ -0,0 +1 @@
noJII7Djv1uQXw1hxEoHxe0LJ2P21uQJ8WryKMPPNb8=

View File

@ -95,6 +95,11 @@ class Selena(discord.Client):
knucklebones_setup(self)
logging.info("Knucklebones module loaded")
if config['modules']['wordle']['enabled']:
from modules.games.wordle import setup as wordle_setup
wordle_setup(self)
logging.info("Wordle module loaded")
if config['modules']['profiles']['enabled']:
from modules.user.profiles import Profiles
profiles = Profiles(self)

166
modules/games/wordle.py Normal file
View File

@ -0,0 +1,166 @@
import discord
import random
import logging
import sqlite3
from datetime import datetime
from discord.ext import tasks
from discord import app_commands
from cryptography.fernet import Fernet
class WordleGame:
def __init__(self, user_id, guild_id, target_word):
self.user_id = user_id
self.guild_id = guild_id
self.target_word = target_word
self.guesses = []
self.max_attempts = 6
def make_guess(self, guess):
if len(guess) != 5 or not guess.isalpha():
raise ValueError("Invalid guess. Must be a 5-letter word.")
feedback = [""] * 5
for i, char in enumerate(guess):
if char == self.target_word[i]:
feedback[i] = "🟩"
elif char in self.target_word:
feedback[i] = "🟨"
self.guesses.append((guess, "".join(feedback)))
return feedback
def is_game_over(self):
return len(self.guesses) >= self.max_attempts or any(guess == self.target_word for guess, _ in self.guesses)
def is_winner(self):
return any(guess == self.target_word for guess, _ in self.guesses)
def render_game(self):
game_board = "\n".join([f"{guess}: {feedback}" for guess, feedback in self.guesses])
return f"```\n{game_board}\n```"
class Wordle:
def __init__(self, bot):
self.bot = bot
self.games = {}
self.logger = logging.getLogger('Wordle')
self.logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(filename='log/selena.log', encoding='utf-8', mode='w')
handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s:%(message)s'))
self.logger.addHandler(handler)
self.db_path = 'data/selena.db'
# Load the word list
self.load_word_list()
self.ensure_table_exists()
def load_word_list(self):
with open('data/wordlist.key', 'rb') as key_file:
key = key_file.read()
cipher_suite = Fernet(key)
with open('data/encrypted_word_list.bin', 'rb') as f:
encrypted_words = f.read().splitlines()
self.word_list = [cipher_suite.decrypt(word).decode() for word in encrypted_words]
def ensure_table_exists(self):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS wordle_games (
user_id TEXT NOT NULL,
guild_id TEXT NOT NULL,
date TEXT NOT NULL,
target_word TEXT NOT NULL,
guesses TEXT,
PRIMARY KEY (user_id, guild_id, date)
);
""")
conn.commit()
conn.close()
def setup(self, tree: app_commands.CommandTree):
@tree.command(name="start_wordle", description="Start a new game of Wordle")
async def start_wordle_command(interaction: discord.Interaction):
user_id = str(interaction.user.id)
guild_id = str(interaction.guild.id)
date_str = datetime.utcnow().strftime('%Y-%m-%d')
# Check if the user has already played today's game
if self.has_played_today(user_id, guild_id, date_str):
await interaction.response.send_message("You have already played today's Wordle. Try again tomorrow!", ephemeral=True)
return
target_word = random.choice(self.word_list)
game = WordleGame(user_id, guild_id, target_word)
self.games[user_id] = game
# Save the game to the database
self.save_game(user_id, guild_id, date_str, target_word)
await interaction.response.send_message(f"New game of Wordle started!\n{game.render_game()}\nMake your guess using /guess_wordle [word]")
@tree.command(name="guess_wordle", description="Make a guess in your Wordle game")
async def guess_wordle_command(interaction: discord.Interaction, guess: str):
user_id = str(interaction.user.id)
game = self.games.get(user_id)
if not game:
await interaction.response.send_message("You don't have an active game. Start one using /start_wordle.", ephemeral=True)
return
try:
feedback = game.make_guess(guess.lower())
if game.is_game_over():
if game.is_winner():
await self.bot.profiles.record_win(user_id, str(interaction.guild.id), "wordle")
await interaction.response.send_message(f"Congratulations! You guessed the word {game.target_word}!\n{game.render_game()}")
else:
await self.bot.profiles.record_loss(user_id, str(interaction.guild.id), "wordle")
await interaction.response.send_message(f"Game over! The word was {game.target_word}.\n{game.render_game()}")
del self.games[user_id]
else:
await interaction.response.send_message(f"{game.render_game()}\nYour guess: {guess}\nFeedback: {''.join(feedback)}")
except ValueError as e:
await interaction.response.send_message(str(e), ephemeral=True)
@tree.command(name="end_wordle", description="End your current game of Wordle")
async def end_wordle_command(interaction: discord.Interaction):
user_id = str(interaction.user.id)
if user_id in self.games:
del self.games[user_id]
await interaction.response.send_message("Your game has been ended.")
else:
await interaction.response.send_message("You don't have an active game to end.", ephemeral=True)
if not tree.get_command("start_wordle"):
tree.add_command(start_wordle_command)
if not tree.get_command("guess_wordle"):
tree.add_command(guess_wordle_command)
if not tree.get_command("end_wordle"):
tree.add_command(end_wordle_command)
def has_played_today(self, user_id, guild_id, date_str):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute("SELECT 1 FROM wordle_games WHERE user_id = ? AND guild_id = ? AND date = ?", (user_id, guild_id, date_str))
result = cursor.fetchone()
conn.close()
return result is not None
def save_game(self, user_id, guild_id, date_str, target_word):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute("INSERT INTO wordle_games (user_id, guild_id, date, target_word) VALUES (?, ?, ?, ?)", (user_id, guild_id, date_str, target_word))
conn.commit()
conn.close()
def setup(bot):
wordle = Wordle(bot)
wordle.setup(bot.tree)
bot.wordle_module = wordle

View File

@ -12,6 +12,7 @@ charset-normalizer==3.3.2
click==8.1.7
colorama==0.4.6
com2ann==0.3.0
cryptography==42.0.8
discord.py==2.3.2
ffmpeg-python==0.2.0
frozenlist==1.4.1