diff --git a/.github/workflows/foundry_release.py b/.github/workflows/foundry_release.py index e85e06e..943bb03 100644 --- a/.github/workflows/foundry_release.py +++ b/.github/workflows/foundry_release.py @@ -3,6 +3,7 @@ import os import re import sys +from html.parser import HTMLParser from pprint import pprint from urllib.parse import urlencode @@ -18,36 +19,13 @@ # GitHub Action Variables UPDATE_DESCRIPTION = bool(int(os.environ.get('UPDATE_DESCRIPTION', '0'))) PUSH_RELEASE = bool(int(os.environ.get('PUSH_RELEASE', '0'))) +POST_UPDATE = bool(int(os.environ.get('POST_UPDATE', '0'))) # Build Variables PROJECT_URL = os.environ['PROJECT_URL'] CHANGES = os.environ['CHANGES'] -def main(): - module_json = get_module_json() - - if PUSH_RELEASE: - push_release(module_json) - else: - print('SKIPPING RELEASE!') - - if UPDATE_DESCRIPTION: - csrf_token, csrf_middleware_token = get_csrf_tokens() - session_id = get_session_id(csrf_token, csrf_middleware_token) - readme = get_readme_as_html() - send_update(csrf_token, csrf_middleware_token, session_id, readme, module_json) - else: - print('SKIPPING FOUNDRY REPO DESCRIPTION UPDATE') - - post_update(module_json['version']) - - -def get_module_json(): - with open('./module.json', 'r') as file: - return json.load(file) - - def push_release(module): conn = http.client.HTTPSConnection("api.foundryvtt.com") conn.request( @@ -104,7 +82,7 @@ def post_auth_login(csrf_token, csrf_middleware_token): conn.request('POST', '/auth/login/', body, headers) response = conn.getresponse() if response.status == 403: - raise Exception('login Fack') + raise Exception(response.reason) cookies = response.getheader('Set-Cookie') session_id = cookies.split('sessionid=')[1].split(';')[0].strip() @@ -112,6 +90,30 @@ def post_auth_login(csrf_token, csrf_middleware_token): return session_id +def extract_errorlist_text(html_string): + class ErrorListParser(HTMLParser): + in_errorlist = False + errorlist_content = [] + + def handle_starttag(self, tag, attrs): + if tag == "ul": + for attr, value in attrs: + if attr == "class" and "errorlist" in value: + self.in_errorlist = True + + def handle_endtag(self, tag): + if tag == "ul" and self.in_errorlist: + self.in_errorlist = False + + def handle_data(self, data): + if self.in_errorlist: + self.errorlist_content.append(data.strip()) + + parser = ErrorListParser() + parser.feed(html_string) + return parser.errorlist_content + + def post_packages_oronder_edit(csrf_token, csrf_middleware_token, session_id, description, module): conn = http.client.HTTPSConnection('foundryvtt.com') headers = { @@ -119,23 +121,23 @@ def post_packages_oronder_edit(csrf_token, csrf_middleware_token, session_id, de 'Content-Type': 'application/x-www-form-urlencoded', 'Cookie': f'csrftoken={csrf_token}; privacy-policy-accepted=accepted; sessionid={session_id}', } - body = urlencode({ - 'username': os.environ.get('FOUNDRY_USERNAME'), - 'title': module['title'], - 'description': description, - 'url': PROJECT_URL, - 'csrfmiddlewaretoken': csrf_middleware_token, - 'author': FOUNDRY_AUTHOR, - 'secret-key': FOUNDRY_PACKAGE_RELEASE_TOKEN, - 'requires': '1', - 'tags': ['15', '17'], - }) + body = urlencode([ + ('username', os.environ.get('FOUNDRY_USERNAME')), + ('title', module['title']), + ('description', description), + ('url', PROJECT_URL), + ('csrfmiddlewaretoken', csrf_middleware_token), + ('author', FOUNDRY_AUTHOR), + ('secret-key', FOUNDRY_PACKAGE_RELEASE_TOKEN), + ('requires', 1), + ('tags', 15), + ('tags', 17) + ]) conn.request('POST', '/packages/oronder/edit', body, headers) response = conn.getresponse() - if response.status != 200: + if response.status != 302: content = response.read().decode() - headers = response.headers.as_string() - err_msg = f'Update Description Failed\n{content=}\n{headers=}' + err_msg = f'Update Description Failed\n{extract_errorlist_text(content)}' raise Exception(err_msg) @@ -157,5 +159,31 @@ def post_update(version): raise Exception(err_msg) +def main(): + with open('./module.json', 'r') as file: + module_json = json.load(file) + + if PUSH_RELEASE: + push_release(module_json) + print('MODULE POSTED TO REPO') + else: + print('SKIPPING RELEASE') + + if UPDATE_DESCRIPTION: + csrf_token, csrf_middleware_token = get_root() + session_id = post_auth_login(csrf_token, csrf_middleware_token) + readme = get_readme_as_html() + post_packages_oronder_edit(csrf_token, csrf_middleware_token, session_id, readme, module_json) + print('REPO DESCRIPTION UPDATED') + else: + print('SKIPPING FOUNDRY REPO DESCRIPTION UPDATE') + + if POST_UPDATE: + post_update(module_json['version']) + print('DISCORD NOTIFIED OF NEW RELEASE') + else: + print('SKIPPING POST TO DISCORD') + + if __name__ == '__main__': main() diff --git a/README.md b/README.md index 64210cd..4be3e26 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,8 @@ -# Oronder: Discord +# Oronder -![](https://img.shields.io/badge/Foundry-v11-informational) -![Latest Release Download Count](https://img.shields.io/github/downloads/oronder/Oronder/latest/module.zip) -![Forge Installs](https://img.shields.io/badge/dynamic/json?label=Forge%20Installs&query=package.installs&suffix=%25&url=https%3A%2F%2Fforge-vtt.com%2Fapi%2Fbazaar%2Fpackage%2Foronder&colorB=4aa94a) +Oronder provides deep Discord integration for Foundry Virtual Tabletop. Access your character sheets, roll for downtime activities, schedule sessions and reward exp all without needing to log back into Foundry. -Oronder provides deep FoundryVTT Discord Integration. Access your character sheets, roll for downtime activities, -schedule sessions and reward exp all without needing to log back into Foundry. Oronder is designed to meet the needs of -running a complex Westmarches game with multiple DMs and players, but also shines for single party campaigns. +Oronder is designed to meet the needs of running a complex Westmarches game with multiple DMs and players, but also shines for single party campaigns. ### Installation Instructions @@ -24,5 +20,4 @@ _The following must be done by the owner of the Discord server you'd like to int Foundry name. For everyone else, you will need to manually add their Discord User Id. - Click `Save Changes`. -Players should now be able to access characters they own in Foundry from Discord. If a PC is not showing up ensure that -player ownership has been assigned and that the character has a class, race and background. \ No newline at end of file +Players should now be able to access characters they own in Foundry from Discord. If a PC is not showing up, ensure that player ownership has been assigned and that the character has a class, race and background. \ No newline at end of file