├── .github ├── ISSUE_TEMPLATE │ ├── add-entry.yml │ └── config.yml ├── add-entry-new.py ├── add-entry.py ├── reset-repo.py ├── verify-staff.py ├── verify.py └── workflows │ ├── add-entry-new.yml │ └── review-entry.yaml ├── .gitignore └── README.md /.github/ISSUE_TEMPLATE/add-entry.yml: -------------------------------------------------------------------------------- 1 | name: Add/Update an entry 2 | description: Add/update an entry to/from the Geode index. 3 | labels: [] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: "## Geode index entry" 8 | - type: input 9 | id: entry 10 | attributes: 11 | label: Your mod link 12 | description: Add a link to your .geode file which can be downloaded directly. 13 | placeholder: "https://github.com///releases/download//.geode" 14 | validations: 15 | required: true 16 | - type: input 17 | id: source-code 18 | attributes: 19 | label: Your mod source code 20 | description: Add a link to the source code of your mod. Required for not verified users. 21 | placeholder: "https://github.com//" 22 | validations: 23 | required: false 24 | - type: textarea 25 | id: description 26 | attributes: 27 | label: Your mod description 28 | description: If you want to shortly explain what your mod does you can do it here. 29 | placeholder: "My mod removes the creator layer from the game, making you unable to play." 30 | validations: 31 | required: false 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Discord link 4 | about: Find us at https://discord.gg/9e43WMKzhp 5 | -------------------------------------------------------------------------------- /.github/add-entry-new.py: -------------------------------------------------------------------------------- 1 | import json 2 | import hashlib 3 | import os 4 | import sys 5 | import zipfile 6 | import urllib.request 7 | import re 8 | from pathlib import Path 9 | import subprocess 10 | 11 | def fail(msg): 12 | print(f'Fail: {msg}', file=sys.stderr) 13 | sys.exit(1) 14 | 15 | 16 | index_path = Path(sys.argv[1]) 17 | issue_author = sys.argv[2] 18 | if len(sys.argv) == 3: 19 | issue_body = os.environ['ISSUE_BODY'] 20 | else: 21 | # not passing issue body as a system argument for injection reasons 22 | # but its still here for testing 23 | issue_body = sys.argv[3] 24 | 25 | is_old = sys.argv[4] == 'old' if len(sys.argv) > 4 else False 26 | 27 | if 'Your mod link' not in issue_body and not is_old: 28 | print('Not a valid index entry', file=sys.stderr) 29 | sys.exit(2) 30 | 31 | # Download the geode file 32 | try: 33 | match = re.search(r'\s*?### Your mod link\s*?(\S+)\s*?', issue_body); 34 | if match: 35 | mod_url = match.group(1) 36 | urllib.request.urlretrieve(mod_url, 'mod.geode') 37 | else: 38 | fail(f'Could not find the geode link') 39 | 40 | except Exception as inst: 41 | fail(f'Could not download the geode file: {inst}') 42 | 43 | # Validate the geode file 44 | try: 45 | archive = zipfile.ZipFile('mod.geode', 'r') 46 | mod_json = json.loads(archive.read('mod.json')) 47 | mod_id = mod_json['id'] 48 | mod_name = mod_json.get('name', mod_id) 49 | mod_version = mod_json['version'].replace('v', '') 50 | 51 | file_list = archive.namelist() 52 | 53 | except Exception as inst: 54 | fail(f'Not a valid geode file: {inst}') 55 | 56 | # check for valid mod id 57 | # TODO: this allows uppercase letters, but fod doesnt like em 58 | MOD_ID_PATTERN = r'^[\w\-]+\.[\w\-]+$' 59 | if (len(mod_id) > 64 or not re.match(MOD_ID_PATTERN, mod_id)) and os.getenv('ACTUALLY_ACCEPTING') != 'YES': 60 | fail(f'Invalid Mod ID: {mod_id}. Must follow this regex: [\w\-]+\.[\w\-]+') 61 | 62 | 63 | # Populate entry.json 64 | try: 65 | mod_platforms = [] 66 | if f"{mod_id}.dylib" in file_list: 67 | mod_platforms.append("macos") 68 | if f"{mod_id}.dll" in file_list: 69 | mod_platforms.append("windows") 70 | if f"{mod_id}.android32.so" in file_list: 71 | mod_platforms.append("android32") 72 | if f"{mod_id}.android64.so" in file_list: 73 | mod_platforms.append("android64") 74 | if f"{mod_id}.ios.dylib" in file_list: 75 | mod_platforms.append("ios") 76 | 77 | mod_tags = mod_json.get("tags", []) 78 | mod_data = open("mod.geode", "rb").read() 79 | mod_hash = hashlib.sha256(mod_data).hexdigest() 80 | 81 | # for backwards compatibility 82 | old_mod_hash = hashlib.sha3_256(mod_data).hexdigest() 83 | 84 | entry_json = { 85 | "commit-author": issue_author, 86 | "platforms": mod_platforms, 87 | "mod": { 88 | "download": mod_url, 89 | "hash": old_mod_hash, 90 | "hash256": mod_hash 91 | }, 92 | "tags": mod_tags 93 | } 94 | except Exception as inst: 95 | fail(f'Could not populate entry.json: {inst}') 96 | 97 | 98 | 99 | # Update the config.json 100 | try: 101 | config_json = json.load(open(index_path / 'config.json', 'r')) 102 | 103 | if 'entries' not in config_json: 104 | config_json['entries'] = {} 105 | 106 | if mod_id not in config_json['entries']: 107 | config_json['entries'][mod_id] = {} 108 | 109 | config_entry = config_json['entries'][mod_id] 110 | 111 | if 'verified' not in config_entry: 112 | config_entry['verified'] = False 113 | 114 | if 'versions' in config_entry: 115 | config_versions = config_entry['versions'] 116 | else: 117 | config_versions = [] 118 | 119 | if config_versions: 120 | old_version = config_versions[-1] 121 | else: 122 | old_version = None 123 | 124 | if mod_version not in config_versions: 125 | config_versions.append(mod_version) 126 | else: 127 | # replacing existing ver :grimacing: 128 | old_version = mod_version 129 | 130 | config_entry['versions'] = config_versions 131 | 132 | json.dump(config_json, open(index_path / 'config.json', 'w'), indent=4) 133 | 134 | except Exception as inst: 135 | fail(f'Could not populate config.json: {inst}') 136 | 137 | 138 | 139 | def write_general_files(general_path): 140 | if 'logo.png' in file_list: 141 | archive.extract('logo.png', path=general_path) 142 | logo_path = (general_path / 'logo.png').as_posix() 143 | # resize mod logos 144 | subprocess.call(['convert', logo_path, '-resize', '336x336>', logo_path]) 145 | if 'about.md' in file_list: 146 | archive.extract('about.md', path=general_path) 147 | if 'changelog.md' in file_list: 148 | archive.extract('changelog.md', path=general_path) 149 | 150 | 151 | def write_version_files(version_path): 152 | json.dump(entry_json, open(version_path / 'entry.json', 'w'), indent=4) 153 | archive.extract('mod.json', path=version_path) 154 | 155 | 156 | # Very sad code i know 157 | def compare_versions(version1, version2): 158 | if '-' not in version1: 159 | version1 += '?' 160 | if '-' not in version2: 161 | version2 += '?' 162 | 163 | return version1 > version2 164 | 165 | 166 | # Fill the directory 167 | try: 168 | mod_directory = index_path / 'mods-v2' / mod_id 169 | version_mod_directory = mod_directory / mod_version 170 | version_mod_directory.mkdir(parents=True, exist_ok=True) 171 | 172 | write_version_files(version_mod_directory) 173 | 174 | latest_version = mod_version 175 | for version in config_versions: 176 | if compare_versions(version, latest_version): 177 | latest_version = version 178 | 179 | if mod_version == latest_version: 180 | write_general_files(mod_directory) 181 | except Exception as inst: 182 | fail(f'Could not populate mod folder {version_mod_directory}: {inst}') 183 | 184 | def send_webhook(mod_id, mod_name, new_version, old_version=None): 185 | from urllib import request 186 | import json 187 | import os 188 | 189 | COLOR = 0x8d73ce 190 | 191 | issue_author = os.getenv('ISSUE_AUTHOR', '?') 192 | comment_author = os.getenv('COMMENT_AUTHOR', '?') 193 | 194 | description = f'''https://geode-sdk.org/mods/{mod_id} 195 | 196 | Uploaded by: [{issue_author}](https://github.com/{issue_author}) 197 | Accepted by: [{comment_author}](https://github.com/{comment_author})''' 198 | 199 | if new_version == old_version: 200 | title = f'Replaced? {mod_name} {new_version}' 201 | elif old_version is None: 202 | title = f'Added {mod_name} {new_version}' 203 | description = 'New mod!\n' + description 204 | else: 205 | title = f'Updated {mod_name} {old_version} -> {new_version}' 206 | 207 | embeds = [ 208 | { 209 | 'color': COLOR, 210 | 'title': title, 211 | 'description': description, 212 | 'thumbnail': { 213 | 'url': f'https://raw.githubusercontent.com/geode-sdk/mods/main/mods-v2/{mod_id}/logo.png' 214 | } 215 | } 216 | ] 217 | 218 | req = request.Request(os.getenv('DISCORD_WEBHOOK_URL'), method='POST') 219 | req.add_header('User-Agent', 'python urllib') 220 | req.add_header('Content-Type', 'application/json') 221 | data = { 222 | 'content': None, 223 | 'embeds': embeds, 224 | } 225 | request.urlopen(req, data=json.dumps(data).encode('utf-8')) 226 | 227 | print(f'''## Info: 228 | * Mod ID: `{mod_id}` 229 | * Version: `{mod_version}` 230 | * Targeting GD: `{mod_json['gd']}` 231 | * Actual platforms: `{mod_platforms}` 232 | * Targeting Geode: `{mod_json['geode']}` 233 | ''') 234 | 235 | potential_issues = [] 236 | if old_version == mod_version: 237 | potential_issues.append(f'Replacing an existing version `{mod_version}`') 238 | if mod_json['gd'] == '*': 239 | potential_issues.append(f'Targeting *any* GD version, make sure you really support that.') 240 | 241 | def check_bad_about(): 242 | if not (mod_directory / 'about.md').exists(): 243 | return True 244 | else: 245 | with open(mod_directory / 'about.md', 'r') as file: 246 | contents = file.read().strip() 247 | lines = contents.splitlines() 248 | if len(lines) == 3 and lines[-1].lower().strip() == 'edit about.md to change this': 249 | return True 250 | return False 251 | 252 | if check_bad_about(): 253 | potential_issues.append('Missing/unchanged `about.md`. Please consider writing one to let the user know what they are downloading.') 254 | 255 | # TODO: check for unchanged logo.png 256 | 257 | if potential_issues: 258 | print('## Potential issues') 259 | print('\n'.join(f'* {x}' for x in potential_issues)) 260 | 261 | if os.getenv('GITHUB_OUTPUT'): 262 | with open(os.getenv('GITHUB_OUTPUT'), 'a') as file: 263 | file.write('has_issues=YES\n') 264 | 265 | 266 | # mod only gets auto accepted when there are no issues 267 | try: 268 | # ignore potential issues if this is triggered by a staff !accept command 269 | if (os.getenv('ACTUALLY_ACCEPTING') == 'YES' or not potential_issues) and os.getenv('VERIFY_USER_RESULT') == 'YES': 270 | send_webhook(mod_id, mod_name, old_version=old_version, new_version=mod_version) 271 | else: 272 | with open('silly_log.txt', 'a') as file: 273 | file.write("not sending webhook :P\n") 274 | except Exception as e: 275 | # dont care about webhook failing 276 | with open('silly_log.txt', 'a') as file: 277 | file.write(str(e) + "\n") 278 | 279 | if os.getenv('GITHUB_OUTPUT'): 280 | with open(os.getenv('GITHUB_OUTPUT'), 'a') as file: 281 | file.write(f'mod_id={mod_id}\n') 282 | -------------------------------------------------------------------------------- /.github/add-entry.py: -------------------------------------------------------------------------------- 1 | import sys, os, json, zipfile, hashlib 2 | from pathlib import Path 3 | from urllib.parse import urlparse 4 | 5 | def fail(folder, msg): 6 | print(f"Could not add mod in folder {folder}: {msg}") 7 | sys.stdout.flush() 8 | os._exit(0) 9 | 10 | folder = Path(sys.argv[1]) 11 | author = sys.argv[2] 12 | 13 | url = sys.argv[3] 14 | repo = "/".join(Path(urlparse(url).path[1:]).parts[:2]) 15 | config_json = json.load(open("config.json", "r")) 16 | 17 | def check_duplicates(mod_id, current_repo): 18 | try: 19 | repositories = config_json["repos"] 20 | 21 | for repo, mods in repositories.items(): 22 | if repo != current_repo and mod_id in mods: 23 | fail(folder, f"A mod with the mod id \"{mod_id}\" already exists") 24 | except: 25 | fail(folder, "Internal error. This is very bad: config.json not found") 26 | 27 | geode_file = folder / "mod.geode" 28 | api_file = folder / "api.zip" 29 | 30 | if not geode_file.exists(): 31 | fail(folder, "Unable to find either mod or api") 32 | 33 | try: 34 | archive = zipfile.ZipFile(geode_file, "r") 35 | mod_json_plaintext = archive.read("mod.json") 36 | mod_json = json.loads(mod_json_plaintext) 37 | archive_files = archive.namelist() 38 | 39 | mod_id = mod_json["id"] 40 | check_duplicates(mod_id, repo) 41 | 42 | platforms = [] 43 | if f"{mod_id}.dylib" in archive_files: 44 | platforms.append("macos") 45 | if f"{mod_id}.dll" in archive_files: 46 | platforms.append("windows") 47 | if f"{mod_id}.so" in archive_files: 48 | platforms.append("android") 49 | if f"{mod_id}.ios.dylib" in archive_files: 50 | platforms.append("ios") 51 | 52 | entry_json = { 53 | "commit-author": author, 54 | "platforms": platforms, 55 | "mod": { 56 | "download": url + "mod.geode", 57 | "hash": hashlib.sha3_256(open(geode_file, "rb").read()).hexdigest() 58 | }, 59 | "tags": mod_json.get("tags", []) 60 | } 61 | 62 | if api_file.exists(): 63 | entry_json["api"] = { 64 | "download": url + "api.zip", 65 | "hash": hashlib.sha3_256(open(api_zip, "rb").read()).hexdigest() 66 | } 67 | except: 68 | fail(folder, "Corrupted mod") 69 | else: 70 | major_version = mod_json["version"].replace("v", "").split(".")[0] 71 | out_folder = Path("mods") / Path(mod_id + "@" + major_version) 72 | out_folder.mkdir(exist_ok=True) 73 | 74 | if "logo.png" in archive_files: 75 | open(out_folder / "logo.png", "wb").write(archive.read("logo.png")) 76 | if "about.md" in archive_files: 77 | open(out_folder / "about.md", "wb").write(archive.read("about.md")) 78 | 79 | json.dump(entry_json, open(out_folder / "entry.json", "w"), indent=4) 80 | open(out_folder / "mod.json", "wb").write(mod_json_plaintext) 81 | 82 | the_repo = config_json["repos"].get(repo, []) 83 | the_repo.append(mod_id) 84 | config_json["repos"][repo] = the_repo 85 | json.dump(config_json, open("config.json", "w"), indent=4) 86 | 87 | print(f"Successfully added {mod_id}") 88 | -------------------------------------------------------------------------------- /.github/reset-repo.py: -------------------------------------------------------------------------------- 1 | import sys, os, shutil, json 2 | from pathlib import Path 3 | from urllib.parse import urlparse 4 | 5 | repo = repo = "/".join(Path(urlparse(sys.argv[1]).path[1:]).parts[:2]) 6 | config = json.load(open("config.json", "r")) 7 | repos = config["repos"] 8 | 9 | if repo not in repos.keys(): 10 | os._exit(0) 11 | 12 | 13 | owned_mods = repos[repo] 14 | 15 | for mod in Path("mods").iterdir(): 16 | if not mod.is_dir(): 17 | continue 18 | 19 | if mod.parts[-1].split("@")[0] in owned_mods: 20 | shutil.rmtree(mod, ignore_errors=True) 21 | 22 | config["repos"][repo] = [] 23 | json.dump(config, open("config.json", "w"), indent=4) -------------------------------------------------------------------------------- /.github/verify-staff.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | from pathlib import Path 4 | 5 | index_path = Path(sys.argv[1]) 6 | issue_author = sys.argv[2] 7 | 8 | config = json.load(open(index_path / "config.json", "r")) 9 | print("YES" if issue_author in config["staff"] else "NO") -------------------------------------------------------------------------------- /.github/verify.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | from pathlib import Path 4 | 5 | index_path = Path(sys.argv[1]) 6 | issue_author = sys.argv[2] 7 | 8 | config = json.load(open(index_path / "config.json", "r")) 9 | print("YES" if issue_author in config["verified"] else "NO") -------------------------------------------------------------------------------- /.github/workflows/add-entry-new.yml: -------------------------------------------------------------------------------- 1 | name: Add entry new 2 | 3 | on: 4 | issues: 5 | types: [opened, edited] 6 | 7 | jobs: 8 | issue_created: 9 | name: Issue test 10 | if: (!github.event.issue.pull_request && github.event.issue.state == 'open') 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout Indexer 14 | uses: actions/checkout@v4 15 | with: 16 | path: code 17 | 18 | - name: Checkout Index 19 | uses: actions/checkout@v4 20 | with: 21 | repository: geode-sdk/mods 22 | path: index 23 | token: '${{ secrets.GEODE_BOT_PUSH_BIN_TOKEN }}' 24 | 25 | - name: Verify User 26 | id: verify_user 27 | shell: bash 28 | run: | 29 | echo result=`python3 code/.github/verify.py index $ISSUE_AUTHOR` >> $GITHUB_OUTPUT 30 | env: 31 | ISSUE_AUTHOR: ${{ github.event.issue.user.login }} 32 | 33 | - name: Add Entry 34 | id: add_entry 35 | shell: bash 36 | run: | 37 | echo has_issues=NO >> $GITHUB_OUTPUT 38 | 39 | set +e 40 | python3 code/.github/add-entry-new.py index $ISSUE_AUTHOR > result.txt 2> err.txt 41 | RESULT=$? 42 | set -e 43 | 44 | echo "output is" 45 | cat result.txt 46 | 47 | echo "any silly errors?" 48 | if [ -f silly_log.txt ]; then 49 | cat silly_log.txt 50 | fi 51 | 52 | EOF=$(openssl rand -hex 8) 53 | 54 | { 55 | echo "issue_output<<$EOF" 56 | cat result.txt 57 | echo "$EOF" 58 | } >> "$GITHUB_OUTPUT" 59 | 60 | { 61 | echo "issue_err<<$EOF" 62 | cat err.txt 63 | echo "$EOF" 64 | } >> "$GITHUB_OUTPUT" 65 | 66 | if [ $RESULT -eq 0 ]; then 67 | echo push_entry=YES >> $GITHUB_OUTPUT 68 | else 69 | echo push_entry=NO >> $GITHUB_OUTPUT 70 | fi 71 | 72 | env: 73 | ISSUE_AUTHOR: ${{ github.event.issue.user.login }} 74 | COMMENT_AUTHOR: ${{ github.event.issue.user.login }} 75 | ISSUE_BODY: ${{ github.event.issue.body }} 76 | DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} 77 | VERIFY_USER_RESULT: ${{ steps.verify_user.outputs.result }} 78 | 79 | - name: Push to index 80 | shell: bash 81 | if: steps.add_entry.outputs.push_entry == 'YES' && steps.verify_user.outputs.result == 'YES' && steps.add_entry.outputs.has_issues == 'NO' 82 | working-directory: ${{ github.workspace }}/index 83 | run: | 84 | git config --local user.email "${{ secrets.GEODE_BOT_EMAIL }}" 85 | git config --local user.name "GeodeBot" 86 | git add -A 87 | git commit -m "Update from $ISSUE_AUTHOR - ${{ steps.add_entry.outputs.mod_id }}" 88 | git remote set-url origin "https://GeodeBot:${{ secrets.GEODE_BOT_PUSH_BIN_TOKEN }}@github.com/geode-sdk/mods.git" 89 | git push -u origin main 90 | env: 91 | ISSUE_AUTHOR: ${{ github.event.issue.user.login }} 92 | 93 | - name: Close because invalid 94 | if: steps.add_entry.outputs.issue_err != '' 95 | run: gh issue close ${{ github.event.issue.number }} --comment "$BODY" -R "${{ github.repository }}" --reason "not planned" 96 | env: 97 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 98 | BODY: "```\n${{ steps.add_entry.outputs.issue_err }}\n```" 99 | 100 | - name: Close because verified and valid 101 | if: steps.verify_user.outputs.result == 'YES' && steps.add_entry.outputs.push_entry == 'YES' && steps.add_entry.outputs.has_issues == 'NO' 102 | run: gh issue close ${{ github.event.issue.number }} --comment "$BODY" -R "${{ github.repository }}" 103 | env: 104 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 105 | BODY: ${{ steps.add_entry.outputs.issue_output }} 106 | 107 | - name: Comment waiting for staff 108 | uses: peter-evans/create-or-update-comment@v4 109 | if: (steps.verify_user.outputs.result == 'NO' || steps.add_entry.outputs.has_issues == 'YES') && steps.add_entry.outputs.push_entry == 'YES' 110 | with: 111 | issue-number: ${{ github.event.issue.number }} 112 | body: | 113 | Waiting for staff to comment "!accept" to accept the entry. 114 | ${{ steps.add_entry.outputs.issue_output }} 115 | -------------------------------------------------------------------------------- /.github/workflows/review-entry.yaml: -------------------------------------------------------------------------------- 1 | name: Review Entry 2 | 3 | on: 4 | issue_comment: 5 | types: [created] 6 | 7 | env: 8 | PR_AUTHOR: ${{ github.event.issue.user.login }} 9 | ISSUE_AUTHOR: ${{ github.event.issue.user.login }} 10 | COMMENT_AUTHOR: ${{ github.event.comment.user.login }} 11 | 12 | jobs: 13 | check_issues: 14 | runs-on: ubuntu-latest 15 | outputs: 16 | dirs: ${{ steps.dirs.outputs.dirs }} 17 | verified: ${{ steps.verify.outputs.verify }} 18 | 19 | if: ${{ !github.event.issue.pull_request }} 20 | 21 | steps: 22 | - name: Checkout Indexer 23 | uses: actions/checkout@v3 24 | with: 25 | path: code 26 | 27 | - name: Checkout Index 28 | uses: actions/checkout@v3 29 | with: 30 | repository: geode-sdk/mods 31 | path: index 32 | token: '${{ secrets.GEODE_BOT_PUSH_BIN_TOKEN }}' 33 | 34 | - name: Verify User 35 | id: verify_user 36 | shell: bash 37 | run: | 38 | echo result=`python3 code/.github/verify-staff.py index $COMMENT_AUTHOR` >> $GITHUB_OUTPUT 39 | 40 | - name: Add Entry 41 | if: steps.verify_user.outputs.result == 'YES' && github.event.comment.body == '!accept' 42 | id: add_entry 43 | shell: bash 44 | run: | 45 | 46 | set +e 47 | python3 code/.github/add-entry-new.py index $ISSUE_AUTHOR >> result.txt 48 | RESULT=$? 49 | set -e 50 | 51 | cat result.txt 52 | 53 | echo "any silly errors?" 54 | if [ -f silly_log.txt ]; then 55 | cat silly_log.txt 56 | fi 57 | 58 | if [ $RESULT -eq 0 ]; then 59 | echo push_entry=YES >> $GITHUB_OUTPUT 60 | else 61 | echo push_entry=NO >> $GITHUB_OUTPUT 62 | fi 63 | 64 | env: 65 | ISSUE_BODY: ${{ github.event.issue.body }} 66 | DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} 67 | VERIFY_USER_RESULT: ${{ steps.verify_user.outputs.result }} 68 | ACTUALLY_ACCEPTING: YES 69 | 70 | - name: Push to index 71 | shell: bash 72 | if: steps.verify_user.outputs.result == 'YES' && steps.add_entry.outputs.push_entry == 'YES' && github.event.comment.body == '!accept' 73 | working-directory: ${{ github.workspace }}/index 74 | run: | 75 | git config --local user.email "${{ secrets.GEODE_BOT_EMAIL }}" 76 | git config --local user.name "GeodeBot" 77 | git add -A 78 | git commit -m "Update from $ISSUE_AUTHOR - ${{ steps.add_entry.outputs.mod_id }}" -m "Accepted by: $COMMENT_AUTHOR" 79 | git remote set-url origin "https://GeodeBot:${{ secrets.GEODE_BOT_PUSH_BIN_TOKEN }}@github.com/geode-sdk/mods.git" 80 | git push -u origin main 81 | 82 | - name: Close Issue 83 | uses: peter-evans/close-issue@v3 84 | if: steps.verify_user.outputs.result == 'YES' && steps.add_entry.outputs.push_entry == 'YES' && github.event.comment.body == '!accept' 85 | with: 86 | issue-number: ${{ github.event.issue.number }} 87 | comment: Successfully added the mod! 88 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows.gitignore 2 | 3 | # Windows thumbnail cache files 4 | Thumbs.db 5 | Thumbs.db:encryptable 6 | ehthumbs.db 7 | ehthumbs_vista.db 8 | 9 | # Dump file 10 | *.stackdump 11 | 12 | # Folder config file 13 | [Dd]esktop.ini 14 | 15 | # Recycle Bin used on file shares 16 | $RECYCLE.BIN/ 17 | 18 | # Windows Installer files 19 | *.cab 20 | *.msi 21 | *.msix 22 | *.msm 23 | *.msp 24 | 25 | # Windows shortcuts 26 | *.lnk 27 | 28 | # MacOS.gitignore 29 | 30 | # General 31 | .DS_Store 32 | .AppleDouble 33 | .LSOverride 34 | 35 | # Icon must end with two \r 36 | Icon 37 | 38 | # Thumbnails 39 | ._* 40 | 41 | # Files that might appear in the root of a volume 42 | .DocumentRevisions-V100 43 | .fseventsd 44 | .Spotlight-V100 45 | .TemporaryItems 46 | .Trashes 47 | .VolumeIcon.icns 48 | .com.apple.timemachine.donotpresent 49 | 50 | # Directories potentially created on remote AFP share 51 | .AppleDB 52 | .AppleDesktop 53 | Network Trash Folder 54 | Temporary Items 55 | .apdisk 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Geode Indexer 2 | 3 | This repository is no longer used for adding new mods to the Geode Mod Index. 4 | 5 | To get your mod listed on the repository, [follow the publishing instructions from the docs.](https://docs.geode-sdk.org/mods/publishing). 6 | --------------------------------------------------------------------------------