├── site ├── .gitignore ├── .prettierrc ├── worker-configuration.d.ts ├── package.json ├── tsconfig.json ├── src │ └── worker.ts └── package-lock.json ├── .github ├── disabled.zip └── workflows │ └── collections-poll-feed.yml ├── .gitignore ├── collections ├── requirements.txt ├── arch │ ├── replace_yml.py │ ├── replacement.py │ ├── produce_yml.py │ ├── add_source.py │ └── poll-hackernews-DEPRECATED.py ├── add-source.py ├── deduplication.py ├── poll-feed.py └── sources.json ├── README.md └── LICENSE /site/.gitignore: -------------------------------------------------------------------------------- 1 | dev 2 | node_modules 3 | .wrangler 4 | wrangler.toml 5 | -------------------------------------------------------------------------------- /site/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 140, 3 | "singleQuote": true, 4 | "semi": true 5 | } 6 | -------------------------------------------------------------------------------- /.github/disabled.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaronsdevera/Personal-News-Feed/HEAD/.github/disabled.zip -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bin 3 | include 4 | lib 5 | pyvenvcfg 6 | .env 7 | .env.local 8 | pyvenv.cfg 9 | .dev.vars 10 | venv -------------------------------------------------------------------------------- /site/worker-configuration.d.ts: -------------------------------------------------------------------------------- 1 | interface Env { 2 | DATA_SINK_URL: string; 3 | AUTH_HEADER_ONE_KEY: string; 4 | AUTH_HEADER_ONE_VALUE: string; 5 | AUTH_HEADER_TWO_KEY: string; 6 | AUTH_HEADER_TWO_VALUE: string; 7 | } 8 | -------------------------------------------------------------------------------- /collections/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2022.12.7 2 | charset-normalizer==3.1.0 3 | feedparser==6.0.10 4 | idna==3.4 5 | numpy==1.24.2 6 | pandas==1.5.3 7 | python-dateutil==2.8.2 8 | pytz==2022.7.1 9 | requests==2.28.2 10 | sgmllib3k==1.0.0 11 | six==1.16.0 12 | urllib3==1.26.14 13 | -------------------------------------------------------------------------------- /site/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chillmilk-c2", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "deploy": "wrangler publish", 7 | "start": "wrangler dev" 8 | }, 9 | "devDependencies": { 10 | "@cloudflare/workers-types": "^4.20230419.0", 11 | "itty-router": "^3.0.12", 12 | "typescript": "^5.0.4", 13 | "wrangler": "^3.0.0" 14 | }, 15 | "dependencies": { 16 | "ua-parser-js": "^1.0.37" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /collections/arch/replace_yml.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | FIND = sys.argv[1] 5 | REPLACE = sys.argv[2] 6 | 7 | workflows = os.listdir('../.github/workflows') 8 | 9 | for workflow in workflows: 10 | if workflow.startswith('run-'): 11 | if workflow.endswith('.yml'): 12 | print(f'Processing {workflow}') 13 | template = open(f'../.github/workflows/{workflow}').read() 14 | template = template.replace(FIND,REPLACE) 15 | open(f'../.github/workflows/{workflow}','w+').write(template) 16 | -------------------------------------------------------------------------------- /collections/arch/replacement.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | dirname = './.github/workflows' 4 | 5 | for filename in os.listdir(dirname): 6 | if filename.endswith('.yml') and 'disabled' not in filename and 'tmp' not in filename: 7 | with open(os.path.join(dirname, filename), 'r') as f: 8 | content = f.read() 9 | content = content.replace(' DATA_SINK_API_KEY: ${{ secrets.DATA_SINK_API_KEY }}', ' AUTH_HEADER_ONE_KEY: ${{ secrets.AUTH_HEADER_ONE_KEY }} \n AUTH_HEADER_ONE_VALUE: ${{ secrets.AUTH_HEADER_ONE_VALUE }} \n AUTH_HEADER_TWO_VALUE: ${{ secrets.AUTH_HEADER_TWO_VALUE }} \n AUTH_HEADER_TWO_KEY: ${{ secrets.AUTH_HEADER_TWO_KEY }} ') 10 | 11 | with open(os.path.join(dirname, filename), 'w') as f: 12 | f.write(content) -------------------------------------------------------------------------------- /collections/arch/produce_yml.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | sources = json.load(open('sources.json')) 4 | 5 | for source in sources: 6 | source_name = source['source_name'] 7 | source_type = source['source_type'] 8 | feed_url = source['url'] 9 | source_name_lower = source_name.lower() 10 | source_name_lower_oneword = source_name.lower().replace(' ','_') 11 | 12 | template = open('../.github/workflows/run-tmp.yml.disabled').read() 13 | 14 | template = template.replace('',source_name_lower) 15 | template = template.replace('',source_name) 16 | template = template.replace('',source_type) 17 | template = template.replace('',feed_url) 18 | open(f'../.github/workflows/run-{source_name_lower_oneword}.yml','w+').write(template) -------------------------------------------------------------------------------- /.github/workflows/collections-poll-feed.yml: -------------------------------------------------------------------------------- 1 | name: collections poll feed 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: '*/15 * * * *' 7 | push: 8 | branches: 9 | - main 10 | 11 | env: 12 | DATA_SINK_URL: ${{ secrets.DATA_SINK_URL }} 13 | AUTH_HEADER_ONE_KEY: ${{ secrets.AUTH_HEADER_ONE_KEY }} 14 | AUTH_HEADER_ONE_VALUE: ${{ secrets.AUTH_HEADER_ONE_VALUE }} 15 | AUTH_HEADER_TWO_VALUE: ${{ secrets.AUTH_HEADER_TWO_VALUE }} 16 | AUTH_HEADER_TWO_KEY: ${{ secrets.AUTH_HEADER_TWO_KEY }} 17 | 18 | jobs: 19 | build: 20 | runs-on: ubuntu-latest 21 | environment: production 22 | 23 | steps: 24 | - uses: actions/checkout@v3 25 | - uses: actions/setup-python@v4 26 | - run: pip install -r collections/requirements.txt; 27 | - name: Poll from feed 28 | run: python3 collections/poll-feed.py collections/sources.json -------------------------------------------------------------------------------- /collections/add-source.py: -------------------------------------------------------------------------------- 1 | import json 2 | import pandas as pd 3 | import datetime 4 | import uuid 5 | import sys 6 | 7 | # function to generate uuid 8 | def generate_uuid(): 9 | return str(uuid.uuid4()) 10 | 11 | if __name__ == '__main__': 12 | 13 | INFILE = sys.argv[1] if len(sys.argv) > 1 else 'sources.json' 14 | 15 | sources = json.load(open(INFILE)) 16 | 17 | df = pd.json_normalize(sources) 18 | 19 | new_source = { 20 | 'active': True, 21 | 'created_at': datetime.datetime.now().isoformat(), 22 | 'id': generate_uuid(), 23 | 'rank': sources[-1]['rank'] + 1 24 | } 25 | 26 | source_name = input('Enter source name: ') 27 | source_type = input('Enter source type (e.g.: news,business,tech,politics,research,blog): ') 28 | url = input('Enter feed url: ') 29 | 30 | new_source.update({ 31 | 'source_name': source_name, 32 | 'source_type': source_type, 33 | 'url': url 34 | }) 35 | 36 | print(new_source) 37 | commit = input('Do you want to add this source? (y/n)') 38 | 39 | if commit.lower() == 'y': 40 | sources.append(new_source) 41 | open(INFILE,'w+').write(json.dumps(sources, indent=4)) 42 | print('Source added successfully') 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Personal-News-Feed 2 | Personal news feed aggregator. 3 | 4 | **[newsfeed.aaronsdevera.com](https://newsfeed.aaronsdevera.com)** 5 | 6 | Inspired by [hackurls](https://hackurls.com/). 7 | 8 | ![Screenshot of my personal news feed website](https://newsfeed.aaronsdevera.com/newsfeed-screenshot.png) 9 | 10 | **Some of my favorite sources** 11 | - [Bloomberg](https://bloomberg.com) 12 | - [HackerNews](https://news.ycombinator.com) 13 | - [ArsTechnica](https://arstechnica.com) 14 | - [The Verge](https://theverge.com) 15 | - [New York Times](https://nytimes.com) 16 | - [Wall Street Journal](https://wsj.com) 17 | 18 | You can view a full list of sources [here in the repo](./collections/sources.json). 19 | **Features** 20 | - No dang ads, cookie modals, etc etc 21 | - Clear highlighting of articles with input keyword 22 | - Dumb easy to update 23 | 24 | **Built with** 25 | - [Cloudflare Workers](https://workers.cloudflare.com/) 26 | - [GitHub Actions](https://github.com/features/actions) 27 | 28 | **Running site in dev mode** 29 | while in the [`site`](site) directory, and assuming you have a `.dev.vars` file with the correct values: 30 | ``` 31 | wrangler dev --live-reload 32 | ``` 33 | 34 | **Deployment** 35 | To deploy the site, while in the [`site`](site) directory: 36 | ``` 37 | wrangler deploy 38 | ``` 39 | 40 | **Adding new sources** 41 | The manual way of doing this is to edit [`collections/sources.json`](./collections/sources.json) and add an entry with the `source_name`, `source_type`, and `url` to the RSS feed. -------------------------------------------------------------------------------- /collections/arch/add_source.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import json 4 | import requests 5 | 6 | NEWSFEED_URL = os.environ.get("NEWSFEED_URL") 7 | NEWSFEED_KEY = os.environ.get("NEWSFEED_KEY") 8 | 9 | SOURCE_NAME = sys.argv[1] 10 | SOURCE_TYPE = sys.argv[2] 11 | SOURCE_URL = sys.argv[3] 12 | 13 | HEADERS = { 14 | "Content-Type": "application/json", 15 | "apikey" : NEWSFEED_KEY, 16 | "Authorization": f"Bearer {NEWSFEED_KEY}" 17 | } 18 | 19 | PAYLOAD = { 20 | "source_name": SOURCE_NAME, 21 | "source_type": SOURCE_TYPE, 22 | "url": SOURCE_URL 23 | } 24 | 25 | r = requests.post( 26 | f"{NEWSFEED_URL}/rest/v1/sources", 27 | headers=HEADERS, 28 | json=PAYLOAD 29 | ) 30 | 31 | if r.status_code == 201: 32 | print("Source added successfully") 33 | 34 | r = requests.get( 35 | f"{NEWSFEED_URL}/rest/v1/sources", 36 | headers=HEADERS 37 | ) 38 | 39 | if r.status_code == 200: 40 | print("Retrieved live list of sources") 41 | sources = r.json() 42 | print("Writing updated list of sources") 43 | open('sources.json','w+').write(json.dumps(sources, indent=4)) 44 | 45 | print("Updating rss collector github actions") 46 | for source in sources: 47 | source_name = source['source_name'] 48 | source_type = source['source_type'] 49 | feed_url = source['url'] 50 | source_name_lower = source_name.lower() 51 | source_name_lower_oneword = source_name.lower().replace(' ','_') 52 | 53 | template = open('../.github/workflows/run-tmp.yml.disabled').read() 54 | 55 | template = template.replace('',source_name_lower) 56 | template = template.replace('',source_name) 57 | template = template.replace('',source_type) 58 | template = template.replace('',feed_url) 59 | open(f'../.github/workflows/run-{source_name_lower_oneword}.yml','w+').write(template) 60 | 61 | print("Operations complete.") -------------------------------------------------------------------------------- /collections/deduplication.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import requests 4 | import pandas as pd 5 | 6 | DOOMPILE_API_URL = os.environ.get("DOOMPILE_API_URL") 7 | DOOMPILE_API_ID = os.environ.get("DOOMPILE_API_ID") 8 | DOOMPILE_API_KEY = os.environ.get("DOOMPILE_API_KEY") 9 | 10 | def run_sql(query: str): 11 | HEADERS = { 12 | 'CF-Access-Client-Id': f'{DOOMPILE_API_ID}', 13 | 'CF-Access-Client-Secret': f'{DOOMPILE_API_KEY}' 14 | } 15 | BODY = { 16 | 'query': f'{query}' 17 | } 18 | r = requests.post(f'{DOOMPILE_API_URL}/sql', 19 | headers=HEADERS, 20 | json=BODY 21 | ) 22 | return r 23 | 24 | def run_search(query: str): 25 | HEADERS = { 26 | 'CF-Access-Client-Id': f'{DOOMPILE_API_ID}', 27 | 'CF-Access-Client-Secret': f'{DOOMPILE_API_KEY}' 28 | } 29 | BODY = { 30 | 'query': { 31 | 'query_string': { 32 | 'query': f'{query}' 33 | } 34 | } 35 | } 36 | r = requests.post(f'{DOOMPILE_API_URL}/search/newsfeed-headlines', 37 | headers=HEADERS, 38 | json=BODY 39 | ) 40 | return r 41 | 42 | def get_records_by_url_sha256(url_sha256: str): 43 | #results = run_sql(f'select * from "newsfeed-headlines" where url_sha256 = \'{url_sha256}\'').json() 44 | try: 45 | results = run_search(f'url_sha256:"{url_sha256}"').json() 46 | except Exception as e: 47 | print(f'[!] Error: {e}') 48 | return None 49 | if 'hits' in list(results.keys()): 50 | if 'hits' in list(results['hits'].keys()): 51 | return pd.json_normalize(results['hits']['hits']).to_dict('records') 52 | else: 53 | print(f'[!] No hits found: {results}') 54 | else: 55 | print(f'[!] No hits found: {results}') 56 | return None 57 | 58 | def delete_record_by_id(id: str): 59 | HEADERS = { 60 | 'CF-Access-Client-Id': f'{DOOMPILE_API_ID}', 61 | 'CF-Access-Client-Secret': f'{DOOMPILE_API_KEY}' 62 | } 63 | 64 | r = requests.get(f'{DOOMPILE_API_URL}/delete/newsfeed-headlines/{id}', 65 | headers=HEADERS 66 | ) 67 | return r 68 | 69 | def get_duplicates(): 70 | results = run_sql('select url_sha256, count(*) as volume from "newsfeed-headlines" group by url_sha256 having count(*) > 1').json() 71 | return pd.DataFrame(results['rows'], columns=[x['name'] for x in results['columns']]).to_dict('records') 72 | 73 | for duplicate_hash in get_duplicates(): 74 | records = get_records_by_url_sha256(duplicate_hash['url_sha256']) 75 | if records: 76 | for record in records[:-1]: 77 | print(f'[!] Deleting record {record["_id"]}') 78 | r = delete_record_by_id(record['_id']) 79 | print(f'[+] Status code: {r.status_code}') 80 | 81 | print(get_duplicates()) -------------------------------------------------------------------------------- /collections/arch/poll-hackernews-DEPRECATED.py: -------------------------------------------------------------------------------- 1 | import os 2 | import feedparser 3 | import requests 4 | import hashlib 5 | import dateutil 6 | import datetime 7 | 8 | DATA_SINK_URL = os.environ.get('DATA_SINK_URL') 9 | DATA_SINK_API_KEY = os.environ.get('DATA_SINK_API_KEY') 10 | 11 | source_name = 'Hacker News' 12 | source_type = 'tech' 13 | base_url = 'https://hacker-news.firebaseio.com/v0' 14 | feed_url= f'{base_url}/topstories.json' 15 | 16 | # function to take sha256 hash of a string 17 | def sha256_hash(string: str): 18 | return hashlib.sha256(string.encode()).hexdigest() 19 | 20 | def sink_data(source_name: str, source_type: str, headline: str, url: str, created_at: str = None): 21 | payload = { 22 | 'source_name': source_name, 23 | 'source_name_sha256': sha256_hash(source_name), 24 | 'source_type': source_type, 25 | 'source_type_sha256': sha256_hash(source_type), 26 | 'headline': headline, 27 | 'headline_sha256': sha256_hash(headline), 28 | 'url': url, 29 | 'url_sha256': sha256_hash(url) 30 | } 31 | if created_at: 32 | payload.update({'created_at': created_at}) 33 | 34 | r = requests.post( 35 | DATA_SINK_URL, 36 | json=payload, 37 | headers={ 38 | 'apikey': DATA_SINK_API_KEY, 39 | 'authorization': f'Bearer {DATA_SINK_API_KEY}' 40 | } 41 | ) 42 | return r 43 | 44 | def check_url(url: str, headline: str): 45 | url_sha256 = sha256_hash(url) 46 | # headline_sha256 = sha256_hash(headline) 47 | # original 48 | #r = requests.get(f'{DATA_SINK_URL}?url_sha256=eq.{url_sha256}&headline_sha256=eq.{headline_sha256}&select=*', 49 | # 50 | r = requests.get(f'{DATA_SINK_URL}?url_sha256=eq.{url_sha256}&select=*', 51 | headers={ 52 | 'apikey': DATA_SINK_API_KEY, 53 | 'authorization': f'Bearer {DATA_SINK_API_KEY}' 54 | } 55 | ) 56 | data = r.json() 57 | if len(data) > 0: 58 | return True 59 | else: 60 | return False 61 | 62 | def poll_feed(source_name: str, source_type: str, feed_url: str): 63 | items = requests.get(feed_url).json() 64 | for item in items: 65 | item_url = f'{base_url}/item/{item}.json' 66 | item_data = requests.get(item_url).json() 67 | created_at = None 68 | try: 69 | created_at = datetime.datetime.fromtimestamp(item_data['time']).isoformat() #dateutil.parser.parse(item_data['time']) 70 | except: 71 | pass 72 | try: 73 | url = item_data['url'] 74 | except: 75 | url = f'https://news.ycombinator.com/item?id={item}' 76 | 77 | headline = item_data['title'] 78 | if not check_url(url,headline): 79 | r = sink_data( 80 | source_name=source_name, 81 | source_type=source_type, 82 | headline=headline, 83 | url=url, 84 | created_at=created_at 85 | ) 86 | if r.status_code not in (201,200): 87 | print(f'Error: {r.status_code} {r.text}') 88 | 89 | poll_feed(source_name, source_type, feed_url) -------------------------------------------------------------------------------- /collections/poll-feed.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import json 4 | import feedparser 5 | import requests 6 | import hashlib 7 | import dateutil 8 | import pandas as pd 9 | import datetime 10 | import uuid 11 | 12 | DATA_SINK_URL = os.environ.get('DATA_SINK_URL') 13 | AUTH_HEADER_ONE_KEY = os.environ.get('AUTH_HEADER_ONE_KEY') 14 | AUTH_HEADER_ONE_VALUE = os.environ.get('AUTH_HEADER_ONE_VALUE') 15 | AUTH_HEADER_TWO_KEY = os.environ.get('AUTH_HEADER_TWO_KEY') 16 | AUTH_HEADER_TWO_VALUE = os.environ.get('AUTH_HEADER_TWO_VALUE') 17 | 18 | # function to take sha256 hash of a string 19 | def sha256_hash(string: str): 20 | return hashlib.sha256(string.encode()).hexdigest() 21 | 22 | # function to generate uuid 23 | def generate_uuid(): 24 | return str(uuid.uuid4()) 25 | 26 | def sink_data(data: dict): 27 | r = requests.post( 28 | f'{DATA_SINK_URL}/index/newsfeed-headlines', 29 | data=json.dumps(data), 30 | headers={ 31 | AUTH_HEADER_ONE_KEY: AUTH_HEADER_ONE_VALUE, 32 | AUTH_HEADER_TWO_KEY: AUTH_HEADER_TWO_VALUE, 33 | 'Content-Type': 'application/json' 34 | } 35 | ) 36 | return r 37 | 38 | def check_url(url_sha256: str, headline_sha256: str): 39 | 40 | query_string = f'url_sha256:"{url_sha256}" OR headline_sha256:"{headline_sha256}"' 41 | 42 | body = { 43 | 'query': { 44 | 'query_string': { 45 | 'query': query_string 46 | } 47 | } 48 | } 49 | 50 | headers = { 51 | AUTH_HEADER_ONE_KEY: AUTH_HEADER_ONE_VALUE, 52 | AUTH_HEADER_TWO_KEY: AUTH_HEADER_TWO_VALUE 53 | } 54 | 55 | target_url = f'{DATA_SINK_URL}/search/newsfeed-headlines' 56 | 57 | try: 58 | r = requests.post(target_url, 59 | headers=headers, 60 | json=body 61 | ) 62 | 63 | try: 64 | data = r.json() 65 | try: 66 | if data['hits']['total']['value'] > 0: 67 | return True 68 | else: 69 | return False 70 | except Exception as e: 71 | print(f'[!] bad response from search: {r.text}') 72 | pass 73 | except Exception as e: 74 | print(f'[!] error checking url: {e}') 75 | pass 76 | 77 | except Exception as e: 78 | print(f'[!] error making request to data sink url: {e}') 79 | pass 80 | return False 81 | 82 | def produce_feed(source_name: str, source_type: str, feed_url: str): 83 | poll_id = generate_uuid() 84 | feed = feedparser.parse(feed_url) 85 | 86 | if feed: 87 | if feed.status in [400,401,403,404,500]: 88 | user_agents = [ 89 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.3', 90 | 'WhatsApp/2.28.1' 91 | ] 92 | for ua in user_agents: 93 | feed = feedparser.parse(feed_url, agent=ua) 94 | if feed.status not in [400,401,403,404,500]: 95 | break 96 | 97 | for entry in feed.entries: 98 | 99 | headline = None 100 | try: 101 | headline = entry.title 102 | except: 103 | pass 104 | url = None 105 | try: 106 | url = entry.link 107 | except: 108 | pass 109 | created_at = None 110 | try: 111 | created_at = entry.published 112 | created_at = dateutil.parser.parse(created_at).isoformat() 113 | except: 114 | pass 115 | 116 | yield { 117 | 'created_at': created_at, 118 | 'poll_id': poll_id, 119 | 'source_name': source_name, 120 | 'source_name_sha256': sha256_hash(source_name), 121 | 'source_type': source_type, 122 | 'source_type_sha256': sha256_hash(source_type), 123 | 'headline': headline, 124 | 'headline_sha256': sha256_hash(headline), 125 | 'url': url, 126 | 'url_sha256': sha256_hash(url) 127 | } 128 | else: 129 | return 130 | 131 | 132 | if __name__ == '__main__': 133 | 134 | if len(sys.argv) < 2: 135 | print('Usage: python3 poll-feed.py ') 136 | sys.exit(1) 137 | 138 | INFILE = sys.argv[1] 139 | 140 | SOURCE_ID = None 141 | 142 | if len(sys.argv) > 2: 143 | SOURCE_ID = sys.argv[2] 144 | 145 | sources = json.load(open(INFILE)) 146 | 147 | if SOURCE_ID: 148 | sources = [source for source in sources if source['id'] == SOURCE_ID] 149 | 150 | for source in sources: 151 | if source['active'] == True: 152 | print('[+] Processing source: ' + source['source_name'] + ' [' + source['source_type'] + ']') 153 | source_name = source['source_name'] 154 | source_type = source['source_type'] 155 | feed_url = source['url'] 156 | 157 | LIMIT = False if source_name not in ['Intelligence Online'] else True 158 | FEED_LIMIT = 50 159 | count = 0 160 | try: 161 | for record in produce_feed(source_name, source_type, feed_url): 162 | print(f'[+] checking record: {record["headline"]}\t{record["url_sha256"]}') 163 | if not check_url(record['url_sha256'], record['headline_sha256']): 164 | print(json.dumps(record)) 165 | r = sink_data( 166 | record 167 | ) 168 | else: 169 | print('[!] record already exists') 170 | count += 1 171 | if LIMIT and count >= FEED_LIMIT: 172 | print(f'[+] reached {FEED_LIMIT} post feed limit for {source_name} [{source_type}]') 173 | break 174 | 175 | except: 176 | print('[!] error processing feed') 177 | pass -------------------------------------------------------------------------------- /site/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, 15 | "lib": ["es2021"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, 16 | "jsx": "react" /* Specify what JSX code is generated. */, 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ 22 | // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | 26 | /* Modules */ 27 | "module": "es2022" /* Specify what module code is generated. */, 28 | // "rootDir": "./", /* Specify the root folder within your source files. */ 29 | "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, 30 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 31 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 32 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 33 | // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ 34 | "types": ["@cloudflare/workers-types"] /* Specify type package names to be included without being referenced in a source file. */, 35 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 36 | "resolveJsonModule": true /* Enable importing .json files */, 37 | // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ 38 | 39 | /* JavaScript Support */ 40 | "allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */, 41 | "checkJs": false /* Enable error reporting in type-checked JavaScript files. */, 42 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ 43 | 44 | /* Emit */ 45 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 46 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 47 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 48 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 49 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ 50 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 51 | // "removeComments": true, /* Disable emitting comments. */ 52 | "noEmit": true /* Disable emitting files from a compilation. */, 53 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 54 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ 55 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 56 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 59 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 60 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 61 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 62 | // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ 63 | // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ 64 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 65 | // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ 66 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 67 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 68 | 69 | /* Interop Constraints */ 70 | "isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */, 71 | "allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */, 72 | // "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, 73 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 74 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, 75 | 76 | /* Type Checking */ 77 | "strict": true /* Enable all strict type-checking options. */, 78 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ 79 | // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ 80 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 81 | // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ 82 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 83 | // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ 84 | // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ 85 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 86 | // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ 87 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ 88 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 89 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 90 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 91 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 92 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 93 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ 94 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 95 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 96 | 97 | /* Completeness */ 98 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 99 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /collections/sources.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "active": true, 4 | "created_at": "2023-03-21T21:06:10.430Z", 5 | "id": "0e263eb1-3c72-406e-9ffb-04de9b45831c", 6 | "rank": 1, 7 | "source_name": "Hacker News", 8 | "source_type": "news", 9 | "url": "https://news.ycombinator.com/rss" 10 | }, 11 | { 12 | "active": true, 13 | "created_at": "2023-03-13T00:51:16.853Z", 14 | "id": "3b64ebde-7a5b-49d0-86cc-a3bc26a749cf", 15 | "rank": 2, 16 | "source_name": "Bloomberg", 17 | "source_type": "business", 18 | "url": "https://news.google.com/rss/search?q=when:7d+allinurl:bloomberg.com&hl=en-US&gl=US&ceid=US:en" 19 | }, 20 | { 21 | "active": true, 22 | "created_at": "2023-03-13T00:51:16.853Z", 23 | "id": "b54fc7df-6442-4280-ab76-d184043194b0", 24 | "rank": 3, 25 | "source_name": "Ars Technica", 26 | "source_type": "tech", 27 | "url": "https://feeds.feedburner.com/arstechnica/index" 28 | }, 29 | { 30 | "active": true, 31 | "created_at": "2023-03-13T00:51:16.853Z", 32 | "id": "25326a5a-4e78-4443-b5e0-4f12ae74c5b3", 33 | "rank": 4, 34 | "source_name": "The Verge", 35 | "source_type": "tech", 36 | "url": "https://www.theverge.com/rss/index.xml" 37 | }, 38 | { 39 | "active": true, 40 | "created_at": "2023-03-13T00:51:16.853Z", 41 | "id": "c27fd3f2-4f7d-4004-8516-c35bd1b59a8d", 42 | "rank": 5, 43 | "source_name": "The Intercept", 44 | "source_type": "politics", 45 | "url": "https://theintercept.com/feed/?lang=en" 46 | }, 47 | { 48 | "active": true, 49 | "created_at": "2023-03-13T00:51:16.853Z", 50 | "id": "5578ecdc-c4c1-41e8-a26f-60df6b82e13a", 51 | "rank": 6, 52 | "source_name": "Neural", 53 | "source_type": "tech", 54 | "url": "https://neural.it/customfeed/all.php" 55 | }, 56 | { 57 | "active": true, 58 | "created_at": "2023-03-13T00:51:16.853Z", 59 | "id": "0430077f-c21a-4075-b83b-7f415246064f", 60 | "rank": 7, 61 | "source_name": "MIT Technology Review", 62 | "source_type": "science", 63 | "url": "https://www.technologyreview.com/feed/" 64 | }, 65 | { 66 | "active": true, 67 | "created_at": "2023-03-13T00:51:16.853Z", 68 | "id": "009f7185-85a6-42aa-839e-5f441836dfdd", 69 | "rank": 8, 70 | "source_name": "Hackaday", 71 | "source_type": "tech", 72 | "url": "https://hackaday.com/blog/feed/" 73 | }, 74 | { 75 | "active": true, 76 | "created_at": "2023-03-13T00:51:16.853Z", 77 | "id": "8fec7ac3-f520-4b8e-8ffa-e0f388ebbcc9", 78 | "rank": 9, 79 | "source_name": "New York Times", 80 | "source_type": "news", 81 | "url": "https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml" 82 | }, 83 | { 84 | "active": true, 85 | "created_at": "2023-03-13T00:51:16.853Z", 86 | "id": "4f276646-b7ef-4fae-abe2-57312ab0c3d6", 87 | "rank": 10, 88 | "source_name": "Wall Street Journal", 89 | "source_type": "news", 90 | "url": "https://feeds.a.dj.com/rss/RSSMarketsMain.xml" 91 | }, 92 | { 93 | "active": true, 94 | "created_at": "2023-03-13T00:51:16.853Z", 95 | "id": "7fe1dc35-c485-485b-bdfe-acf9fa43cb51", 96 | "rank": 11, 97 | "source_name": "Roll Call", 98 | "source_type": "politics", 99 | "url": "https://nitter.net/rollcall/rss" 100 | }, 101 | { 102 | "active": true, 103 | "created_at": "2023-03-13T00:51:16.853Z", 104 | "id": "49c5eb4b-13c7-4dda-9201-f06ecca59d6b", 105 | "rank": 12, 106 | "source_name": "Nature", 107 | "source_type": "science", 108 | "url": "https://www.nature.com/nature.rss" 109 | }, 110 | { 111 | "active": true, 112 | "created_at": "2023-03-13T00:51:16.853Z", 113 | "id": "0baad7a4-ef07-4795-8eaa-ea92770d8fdc", 114 | "rank": 13, 115 | "source_name": "The Guardian", 116 | "source_type": "news", 117 | "url": "https://www.theguardian.com/world/rss" 118 | }, 119 | { 120 | "active": true, 121 | "created_at": "2023-03-13T00:51:16.853Z", 122 | "id": "3b96d1e6-c17e-4da8-8264-b74cb5173999", 123 | "rank": 14, 124 | "source_name": "Wired", 125 | "source_type": "tech", 126 | "url": "https://www.wired.com/feed/category/business/latest/rss" 127 | }, 128 | { 129 | "active": true, 130 | "created_at": "2023-03-13T00:51:16.853Z", 131 | "id": "a7617a4f-174c-4895-8e99-f5a800d7c67c", 132 | "rank": 15, 133 | "source_name": "Harvard Business Review", 134 | "source_type": "business", 135 | "url": "https://tagteam.harvard.edu/hub_feeds/924/feed_items.rss" 136 | }, 137 | { 138 | "active": true, 139 | "created_at": "2023-03-13T00:51:16.853Z", 140 | "id": "d2d1cb3d-5ad3-4482-9136-261ead64f1ad", 141 | "rank": 16, 142 | "source_name": "StackOverflow", 143 | "source_type": "tech", 144 | "url": "https://stackoverflow.blog/feed/" 145 | }, 146 | { 147 | "active": true, 148 | "created_at": "2023-03-13T00:51:16.853Z", 149 | "id": "7fa54845-8580-4154-b3f9-ba53ec79253f", 150 | "rank": 17, 151 | "source_name": "The New Yorker", 152 | "source_type": "news", 153 | "url": "https://www.newyorker.com/feed/everything" 154 | }, 155 | { 156 | "active": true, 157 | "created_at": "2023-03-13T00:51:16.853Z", 158 | "id": "a724efb4-b6a9-44d2-a912-fab9acce570a", 159 | "rank": 18, 160 | "source_name": "DoJ", 161 | "source_type": "news", 162 | "url": "https://www.justice.gov/feeds/justice-news.xml?type%5Bpress_release%5D=press_release&component%5B376%5D=376&organization=All" 163 | }, 164 | { 165 | "active": true, 166 | "created_at": "2023-03-13T00:51:16.853Z", 167 | "id": "9cf70dc7-8759-46c6-8584-82f759a069ed", 168 | "rank": 19, 169 | "source_name": "The Information", 170 | "source_type": "tech", 171 | "url": "https://www.theinformation.com/feed" 172 | }, 173 | { 174 | "active": true, 175 | "created_at": "2023-03-13T01:08:59.349Z", 176 | "id": "abcb1893-1460-4e24-aa5e-75e068ae786e", 177 | "rank": 20, 178 | "source_name": "Eugene Yan", 179 | "source_type": "blog", 180 | "url": "https://eugeneyan.com/rss/" 181 | }, 182 | { 183 | "active": true, 184 | "created_at": "2023-03-13T01:11:47.053Z", 185 | "id": "56c01fa9-b49e-43c9-8c69-e419cb9e24c8", 186 | "rank": 21, 187 | "source_name": "The Grugq", 188 | "source_type": "blog", 189 | "url": "https://grugq.substack.com/feed" 190 | }, 191 | { 192 | "active": true, 193 | "created_at": "2023-03-13T01:25:34.439Z", 194 | "id": "f1aaeb11-61cb-42b6-8bb5-d3987a948011", 195 | "rank": 22, 196 | "source_name": "Risky Business", 197 | "source_type": "blog", 198 | "url": "https://riskybiznews.substack.com/feed" 199 | }, 200 | { 201 | "active": true, 202 | "created_at": "2023-03-13T01:26:26.759Z", 203 | "id": "cee8c7a8-f33e-454c-9b9c-a63608cdebfd", 204 | "rank": 23, 205 | "source_name": "lcamtuf", 206 | "source_type": "blog", 207 | "url": "https://lcamtuf.substack.com/feed" 208 | }, 209 | { 210 | "active": true, 211 | "created_at": "2023-03-13T01:27:08.484Z", 212 | "id": "007f681f-d413-4684-b69f-e0d902eb51c7", 213 | "rank": 24, 214 | "source_name": "Matt Tait", 215 | "source_type": "blog", 216 | "url": "https://www.pwnallthethings.com/feed" 217 | }, 218 | { 219 | "active": true, 220 | "created_at": "2023-03-13T01:27:57.127Z", 221 | "id": "f9d844e0-b74a-42c6-b017-219eeb2eb408", 222 | "rank": 25, 223 | "source_name": "Steve Vladeck", 224 | "source_type": "blog", 225 | "url": "https://stevevladeck.substack.com/feed" 226 | }, 227 | { 228 | "active": true, 229 | "created_at": "2023-03-13T01:28:13.910Z", 230 | "id": "af013af4-2352-425a-baa8-3c60eef71b9e", 231 | "rank": 26, 232 | "source_name": "Ben Wittes", 233 | "source_type": "blog", 234 | "url": "https://www.dogshirtdaily.com/feed" 235 | }, 236 | { 237 | "active": true, 238 | "created_at": "2023-03-13T01:31:29.345Z", 239 | "id": "e0d23bb1-905a-4ef1-bbbf-780448c39061", 240 | "rank": 27, 241 | "source_name": "Shannon Liao", 242 | "source_type": "blog", 243 | "url": "https://shannonliao.substack.com/feed" 244 | }, 245 | { 246 | "active": true, 247 | "created_at": "2023-03-13T01:31:56.262Z", 248 | "id": "26c8f197-b40d-4d82-9cb5-4fdf13d8d429", 249 | "rank": 28, 250 | "source_name": "Shoshana Wodinsky", 251 | "source_type": "blog", 252 | "url": "https://swodinsky.substack.com/feed" 253 | }, 254 | { 255 | "active": true, 256 | "created_at": "2023-03-13T01:32:30.060Z", 257 | "id": "9929ae3c-38c0-445a-8aa5-c2ca09ab7c3f", 258 | "rank": 29, 259 | "source_name": "Conspirador Norteno", 260 | "source_type": "blog", 261 | "url": "https://conspirator0.substack.com/feed" 262 | }, 263 | { 264 | "active": true, 265 | "created_at": "2023-03-24T14:58:16.295Z", 266 | "id": "f354a72f-b445-4981-b87f-da529a2e3f2a", 267 | "rank": 30, 268 | "source_name": "Joshua Citarella", 269 | "source_type": "blog", 270 | "url": "https://joshuacitarella.substack.com/feed" 271 | }, 272 | { 273 | "active": true, 274 | "created_at": "2023-04-04T03:39:51.782Z", 275 | "id": "a4635692-d8d8-4cb6-9a68-297ba9386ac2", 276 | "rank": 31, 277 | "source_name": "Molly White", 278 | "source_type": "blog", 279 | "url": "https://newsletter.mollywhite.net/feed" 280 | }, 281 | { 282 | "active": true, 283 | "created_at": "2023-04-13T12:27:45.857Z", 284 | "id": "c57b8b6e-9a0d-44ad-8eb0-fad9919c40bf", 285 | "rank": 32, 286 | "source_name": "Convex Value", 287 | "source_type": "blog", 288 | "url": "https://convex.substack.com/feed" 289 | }, 290 | { 291 | "active": true, 292 | "created_at": "2023-08-20T07:30:35.363Z", 293 | "id": "1f245c32-3fca-47be-850b-2998ebb88601", 294 | "rank": 33, 295 | "source_name": "Cyber Defence Analysis", 296 | "source_type": "blog", 297 | "url": "https://bluepurple.binaryfirefly.com/feed" 298 | }, 299 | { 300 | "active": true, 301 | "created_at": "2023-08-20T07:32:45.849Z", 302 | "id": "6d9693af-32c7-4d9d-b893-90187f148003", 303 | "rank": 34, 304 | "source_name": "Intrusion Truth", 305 | "source_type": "blog", 306 | "url": "https://intrusiontruth.wordpress.com/feed" 307 | }, 308 | { 309 | "active": true, 310 | "created_at": "2023-08-20T07:34:13.518Z", 311 | "id": "eb766f30-5fc6-4faa-971e-dbe60d0e5d3b", 312 | "rank": 35, 313 | "source_name": "KrebsOnSecurity", 314 | "source_type": "blog", 315 | "url": "https://krebsonsecurity.com/feed/" 316 | }, 317 | { 318 | "active": true, 319 | "created_at": "2023-08-20T07:34:53.126Z", 320 | "id": "491774a0-82b0-4f93-8b7d-1f8507e79614", 321 | "rank": 36, 322 | "source_name": "Cory Doctorow", 323 | "source_type": "blog", 324 | "url": "https://craphound.com/feed/" 325 | }, 326 | { 327 | "active": true, 328 | "created_at": "2023-08-20T07:35:35.750Z", 329 | "id": "61c47bb4-f32f-4d91-959d-01c7834397d4", 330 | "rank": 37, 331 | "source_name": "Slicletter", 332 | "source_type": "blog", 333 | "url": "https://slic.substack.com/feed" 334 | }, 335 | { 336 | "active": true, 337 | "created_at": "2023-08-20T07:52:15.727Z", 338 | "id": "0f7d0865-1949-4ad2-a2e6-3a3c8d55ce95", 339 | "rank": 38, 340 | "source_name": "Arxiv Human Computer Interaction", 341 | "source_type": "research", 342 | "url": "http://arxiv.org/rss/cs.HC" 343 | }, 344 | { 345 | "active": true, 346 | "created_at": "2023-08-20T07:52:16.642Z", 347 | "id": "19f84d71-5f06-4b2b-ba96-08f8e0e4c133", 348 | "rank": 39, 349 | "source_name": "Arxiv Computers and Society", 350 | "source_type": "research", 351 | "url": "http://arxiv.org/rss/cs.CY" 352 | }, 353 | { 354 | "active": true, 355 | "created_at": "2023-08-20T07:52:17.332Z", 356 | "id": "1c6aabb3-f5dd-45a2-8c96-b14fdbd82eb7", 357 | "rank": 40, 358 | "source_name": "Arxiv Cryptography and Security", 359 | "source_type": "research", 360 | "url": "http://arxiv.org/rss/cs.CR" 361 | }, 362 | { 363 | "active": true, 364 | "created_at": "2023-08-20T07:52:18.086Z", 365 | "id": "7110e58e-624a-403f-ac90-b4bfde1b1af9", 366 | "rank": 41, 367 | "source_name": "Arxiv Artificial Intelligence", 368 | "source_type": "research", 369 | "url": "http://arxiv.org/rss/cs.AI" 370 | }, 371 | { 372 | "active": true, 373 | "created_at": "2023-08-20T07:52:18.881Z", 374 | "id": "0d1c703b-1f7a-4315-b151-19e08f311bf0", 375 | "rank": 42, 376 | "source_name": "Arxiv Computers Game Theory", 377 | "source_type": "research", 378 | "url": "http://arxiv.org/rss/cs.GT" 379 | }, 380 | { 381 | "active": true, 382 | "created_at": "2023-08-20T07:52:19.592Z", 383 | "id": "529a21ab-f2c8-4966-9ac1-b9450e19ba7a", 384 | "rank": 43, 385 | "source_name": "Arxiv Social Networks", 386 | "source_type": "research", 387 | "url": "http://arxiv.org/rss/cs.SI" 388 | }, 389 | { 390 | "active": true, 391 | "created_at": "2023-08-20T07:52:20.313Z", 392 | "id": "af82282c-9d96-45e1-b6d7-c08a9c8b2643", 393 | "rank": 44, 394 | "source_name": "Arxiv Information Retrieval", 395 | "source_type": "research", 396 | "url": "http://arxiv.org/rss/cs.IR" 397 | }, 398 | { 399 | "active": true, 400 | "created_at": "2023-08-20T07:52:21.080Z", 401 | "id": "f256ee10-5bd6-487e-bdf6-981fc134cb37", 402 | "rank": 45, 403 | "source_name": "Arxiv Information Theory", 404 | "source_type": "research", 405 | "url": "http://arxiv.org/rss/cs.IT" 406 | }, 407 | { 408 | "active": true, 409 | "created_at": "2023-08-20T07:53:45.972Z", 410 | "id": "e2fca62c-9271-463d-9b51-7e4e8fe5d302", 411 | "rank": 46, 412 | "source_name": "Hellgate", 413 | "source_type": "news", 414 | "url": "https://hellgatenyc.com/feed" 415 | }, 416 | { 417 | "active": true, 418 | "created_at": "2023-08-20T08:02:40.358Z", 419 | "id": "28fdac9a-6b92-4b47-b003-0f815edbaebe", 420 | "rank": 47, 421 | "source_name": "Simon Willison", 422 | "source_type": "blog", 423 | "url": "https://simonwillison.net/atom/everything/" 424 | }, 425 | { 426 | "active": true, 427 | "created_at": "2023-08-20T08:16:29.900Z", 428 | "id": "7cc8027b-f082-4432-918a-ae083b8f659e", 429 | "rank": 48, 430 | "source_name": "Berkman Klein Center", 431 | "source_type": "blog", 432 | "url": "https://medium.com/feed/berkman-klein-center" 433 | }, 434 | { 435 | "active": true, 436 | "created_at": "2023-08-20T08:37:37.938Z", 437 | "id": "81c20c1f-4560-4da3-b18a-1ff9e475c14d", 438 | "rank": 49, 439 | "source_name": "Intelligence Online", 440 | "source_type": "news", 441 | "url": "http://feeds.feedburner.com/IntelligenceOnline" 442 | }, 443 | { 444 | "active": true, 445 | "created_at": "2023-08-20T08:41:51.738Z", 446 | "id": "5d396bcf-7029-4248-98ed-49767bbef143", 447 | "rank": 50, 448 | "source_name": "StratFor", 449 | "source_type": "news", 450 | "url": "http://www.stratfor.com/rss.xml" 451 | }, 452 | { 453 | "active": true, 454 | "created_at": "2023-08-20T08:42:47.127Z", 455 | "id": "80c0dd52-4eea-4bf4-b38d-f5fef44048e6", 456 | "rank": 51, 457 | "source_name": "The Diplomat", 458 | "source_type": "news", 459 | "url": "https://thediplomat.com/category/blogs/feed/" 460 | }, 461 | { 462 | "active": true, 463 | "created_at": "2023-08-20T08:44:53.137Z", 464 | "id": "be6739e2-8808-4ad4-a598-e5c05c73d992", 465 | "rank": 52, 466 | "source_name": "Reuters", 467 | "source_type": "news", 468 | "url": "https://www.reutersagency.com/feed/" 469 | }, 470 | { 471 | "active": true, 472 | "created_at": "2023-08-20T08:47:59.953Z", 473 | "id": "03c13bb9-1bb5-4e68-bf25-b354bf32c687", 474 | "rank": 53, 475 | "source_name": "Financial Times", 476 | "source_type": "news", 477 | "url": "https://www.ft.com/rss/home/uk" 478 | }, 479 | { 480 | "active": false, 481 | "created_at": "2023-08-20T08:52:03.101Z", 482 | "id": "01988ef9-c5ff-4984-a34f-2ec8fe48b2f1", 483 | "rank": 54, 484 | "source_name": "Global Newswire Analysis", 485 | "source_type": "business", 486 | "url": "https://www.globenewswire.com/RssFeed/subjectcode/3-Analyst%20Recommendations/feedTitle/GlobeNewswire%20-%20Analyst%20Recommendations" 487 | }, 488 | { 489 | "active": false, 490 | "created_at": "2023-08-20T08:56:31.434Z", 491 | "id": "7e68a7bc-55d5-4343-a55d-4808119c9494", 492 | "rank": 55, 493 | "source_name": "Global Newswire Contracts", 494 | "source_type": "business", 495 | "url": "https://www.globenewswire.com/RssFeed/subjectcode/7-Business%20Contracts/feedTitle/GlobeNewswire%20-%20Business%20Contracts" 496 | }, 497 | { 498 | "active": false, 499 | "created_at": "2023-08-20T08:56:32.028Z", 500 | "id": "4ba902c2-c5ac-4285-8c2c-d300e0f56697", 501 | "rank": 56, 502 | "source_name": "Global Newswire Research", 503 | "source_type": "business", 504 | "url": "https://www.globenewswire.com/RssFeed/subjectcode/14-Economic%20Research%20And%20Reports/feedTitle/GlobeNewswire%20-%20Economic%20Research%20And%20Reports" 505 | }, 506 | { 507 | "active": true, 508 | "created_at": "2023-08-22T21:23:40.319Z", 509 | "id": "1f821b2c-5c31-4ca4-9ca6-8dfeffafa29e", 510 | "rank": 57, 511 | "source_name": "404media", 512 | "source_type": "news", 513 | "url": "https://www.404media.co/rss/" 514 | }, 515 | { 516 | "active": true, 517 | "created_at": "2024-01-08T16:15:40.319Z", 518 | "id": "1d345acd9-0c22-4d07-9ae4-c0de4e9161ee", 519 | "rank": 58, 520 | "source_name": "GM NYC", 521 | "source_type": "events", 522 | "url": "https://www.gmnyc.com/feed" 523 | }, 524 | { 525 | "active": true, 526 | "created_at": "2024-01-19T03:02:00.001Z", 527 | "id": "1f487e0c8-c78f-4b3c-a4c8-5a976a3f7bdb", 528 | "rank": 59, 529 | "source_name": "CTL ALT DEL Blog", 530 | "source_type": "blog", 531 | "url": "https://controlaltdelete.technology/rss/feed.rss" 532 | }, 533 | { 534 | "active": true, 535 | "created_at": "2024-01-27T11:37:00.001Z", 536 | "id": "0e921678-b8cc-40be-b82f-072a866406d6", 537 | "rank": 60, 538 | "source_name": "Hardcore Software", 539 | "source_type": "blog", 540 | "url": "https://hardcoresoftware.learningbyshipping.com/feed.rss" 541 | }, 542 | { 543 | "active": true, 544 | "created_at": "2024-01-30T11:42:00.001Z", 545 | "id": "99c0664b-9a26-4457-81bc-e5029571fc84", 546 | "rank": 61, 547 | "source_name": "The Record", 548 | "source_type": "tech", 549 | "url": "https://therecord.media/feed/" 550 | }, 551 | { 552 | "active": true, 553 | "created_at": "2024-01-30T12:42:00.001Z", 554 | "id": "fd537f13-02e2-4ceb-b30b-0d8f5f73426d", 555 | "rank": 62, 556 | "source_name": "Foreign Affairs", 557 | "source_type": "news", 558 | "url": "https://www.foreignaffairs.com/rss.xml" 559 | }, 560 | { 561 | "active": true, 562 | "created_at": "2024-01-30T12:43:00.001Z", 563 | "id": "5612af23-92ee-4698-bbe3-9f8c83446a0e", 564 | "rank": 63, 565 | "source_name": "Muddy Waters Research", 566 | "source_type": "business", 567 | "url": "https://www.muddywatersresearch.com/feed" 568 | }, 569 | { 570 | "active": true, 571 | "created_at": "2024-01-30T13:04:00.001Z", 572 | "id": "8ba44c30-2edc-4007-8ffc-bea894dfe0e4", 573 | "rank": 64, 574 | "source_name": "Venture Capital Journal", 575 | "source_type": "business", 576 | "url": "https://www.venturecapitaljournal.com/rss" 577 | }, 578 | { 579 | "active": true, 580 | "created_at": "2024-04-19T16:50:36.999800", 581 | "id": "eb10a905-d6e5-482e-8e26-c626ddbfa550", 582 | "rank": 65, 583 | "source_name": "Rhizome", 584 | "source_type": "tech", 585 | "url": "https://feeds.feedburner.com/TheRhizomeBlogRss" 586 | }, 587 | { 588 | "active": true, 589 | "created_at": "2024-04-19T16:52:25.883244", 590 | "id": "2c9b9da1-a741-42c4-a1d8-5c80bce8eec9", 591 | "rank": 66, 592 | "source_name": "Reboot", 593 | "source_type": "tech", 594 | "url": "https://joinreboot.org/feed" 595 | }, 596 | { 597 | "active": true, 598 | "created_at": "2024-04-19T16:55:37.702523", 599 | "id": "d738a2ae-fbd6-472b-80dc-78e6ff7d4d0e", 600 | "rank": 67, 601 | "source_name": "Do Not Research", 602 | "source_type": "tech", 603 | "url": "https://donotresearch.substack.com/feed" 604 | }, 605 | { 606 | "active": true, 607 | "created_at": "2024-04-19T16:53:47.892372", 608 | "id": "f317b01f-320c-448c-993f-4824055cd53c", 609 | "rank": 68, 610 | "source_name": "Lobsters", 611 | "source_type": "tech", 612 | "url": "https://lobste.rs/rss" 613 | }, 614 | { 615 | "active": true, 616 | "created_at": "2024-05-07T06:52:29.223350", 617 | "id": "8a4cf1c7-a96e-4a9a-b9f6-08664531e60b", 618 | "rank": 69, 619 | "source_name": "The Stack", 620 | "source_type": "tech", 621 | "url": "https://www.thestack.technology/latest/rss/" 622 | }, 623 | { 624 | "active": true, 625 | "created_at": "2024-08-16T00:41:12.991895", 626 | "id": "64976dbd-0ff4-4a7a-bc1a-180b53e1c85b", 627 | "rank": 70, 628 | "source_name": "Exploits Club", 629 | "source_type": "blog", 630 | "url": "https://blog.exploits.club/rss" 631 | } 632 | ] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /site/src/worker.ts: -------------------------------------------------------------------------------- 1 | const favicon_ico = `AAABAAMAEBAAAAEAIABoBAAANgAAACAgAAABACAAKBEAAJ4EAAAwMAAAAQAgAGgmAADGFQAAKAAAABAAAAAgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////////////////////////+np6v/i4uP//////////////////////729vf+ampr/3Nzc///////////////////////w8fH/zczR/6uqtf98e4f/hION/9fX2v///////////////v+xsbv/19Tr/2xrc//o6Oj/+fn6/8vLzf+qqbD/e3qD/21sdf9gX2f/cHB4/2Zmbv90c3v/09PX/+Tk5P/m5ub/6ejp/7y7xv+Tkp3/rq2v/5iXmv9pZ3H/VVVb/3x7hP+Ego3/goGM/2Niaf92dX7/jYyT/8TEyP/+/v7/8PDw/729vf/n6Of/zMzM///////4+Pj/pqar/3d3gP9zcnv/hYSK/7Gxtf/MzM7/8PDw//7//v/+/v7///////r6+v/Jycn/wMDA/9TU1P/n5+f///////7+/v/X19f/6enp/9nZ2v/Hxsv/wsHJ/769yf+ysMD/j46Z/8PDxv/+/v7///////////////////////////////////7+/6inrf+oprn/rqy//7e1yf+sqrz/sbDC/5CPnv+ko7X/sK67/+Dg4f////////////////////////////n5+f+gnq7/mpim/39+if93doD/X19m/8fF2P+Mipr/ysff/8LA1v/Jx9L////////////////////////////+//7/pqSz/3Nxe/+BgI3/iYiV/4mIlf+9u87/jo2c/8vI4f/Cv9b/u7nF///////////////////////g4OD//v7+/5+eqv9niHX/RItX/1Gtaf9Ms2f/c6WF/5qZqf/Jx97/zsvj/7i1xP//////////////////////zs7O/8DAwP+dnKb/Pp9Z/yqlRf8okT7/MdFW/1+zd/+qqLr/u7jO/87L4/+6uMj//////////////////////+Tk5P/m5ub/ubfA/0WUXf8rsUr/MNBW/yyvSv9Osmf/tLLF/6upvf/Oy+T/srDB///+/v///////////////////////////8nI0f9Heln/NqpT/z+jWv9BkFj/Xohv/7m4zP+xr8P/zsvk/7Syxf////7////////////////////////////Fxcv/m5mp/5aVpP+Yl6b/p6a3/7Syxf+jorT/qKa5/7GvxP+jobD///7+////////////////////////////7e3t/8LCw//Ix87/t7bC/6+tu/+9vML/ycnO/9DQ1/++vsH/5OTk///////////////////////////////////////////////////////+/v7///////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAACAAAABAAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////v7+//v7+//+/v7/////////////////////////////////////////////////////////////////////////////////6Onp/76+wv+hoab/6urq///////////////////////////////////////+/v7/lpaW/2BgYP9GRkb/Kior/3d3eP/9/f3////////////////////////////////////////////////////////////29vb/xcbI/7Oyu/+hoLD/sK7A/4+Pmf+6uMb/3d3e///+/////////////////////////////////v+amZ7/nJur/8C+0//c2vD/UFBa/52dnf////////////////////////////////////////////z8/P/Iycr/p6as/5eWov+lo7T/kY+d/0lJT/9WVV7/WFhf/29vd/+Yl6L/6erq/////////////////////////////v7+/8jIyv/Ix9n/4N31/+Dd9f+1ssb/Dg4P/6SkpP///v7//////////////////v7+/9vc3f+5ub3/h4aP/6Shr/+Zl6X/b295/1pZYf9dXWP/dnV//29udv9XV1//cW96/2tqcf+Pj5f/5+fo/////////////////////////////v7+/6uqrv+6uMr/urjM/62rvP+Fg4//MTA1/93d3f//////6enq/769wP9zc3j/iomU/4mIk/9ubnb/UlJZ/0JBR/9oZ2//jYyY/zo5P/9zc3r/aWhw/2Zmbf9ranL/U1JY/4GAiv+koq//xMTF/7/AwP/S0tL/z8/P/8vLy//8/Pz//v7+/9rb2/+jo6n/j46X/4yLkf+zs7X/9vb2/7a1t/9+fYX/l5Wi/2Vjbf9JSU7/PDxA/2hob/+Mi5X/bmx3/5yap/94d4H/hISP/zw8QP9bWmH/ZWVq/2pqcf9YV13/ZmRt/4iHk/+0tLb//v7+//7+/v/+/v7/6+vr/5qamv/W1tb/2NnY/9TV1f+rq6v/29vb////////////0dHR/1pZXf8vLzT/eHaA/2tqcv9lZG3/hYSP/3Vzfv+OjZb/d3V//46MmP9/f4n/mpik/1lYX/+cmqj/bWxz/7Oxuf/ExMn/2Nja//7+/v/////////////////Y2Nj/zMzM/7e3t//5+fn/+Pj4/9PT0//Z2dn//v7+////////////4+Pj/3t6f/+sqrj/cW96/4KCiv99fYf/amlx/3p5gv+KiJP/fX2E/4GAiP97e4D/ubm7/8nKyf/4+Pj//v79//7//v////7//////////////////////+zs7P+2trb/qqqq/8vLy/+ysrL/4eHh/93d3f+zs7P/////////////////9fX1/35+gv9aWmD/kI+a/4SCjf9gX2X/c3N2/56en//Ozs7/+vr5//7+/v/+/v7///////////////////////z8/P/+/v7///////////////////////j4+P/Ozs7/t7e3/8zMzP/S0tL/v7+//+vr6////////////////////////Pz8/8DAwf+dnZ7/zMzM//f39//+/v7//v7+///+///+/v7/+vv7/+Dg4P/Ix8j/sbG0/56eo/+RkJn/dHN9/4GAg//r6+z////+///////////////////////+/v7////////////+/v7////////////////////////////////////////////+/v7/5eXl/8PDxP+lpKf/j4+U/5CPmv+SkJ7/nJmr/7W0yf/KyN//zsrk/8rI3/+Uk6L/tLLE/399iP+kpKb//Pz8/////v///////////////////////////////////////////////////////////////////////////+Pk4/96eob/uLfM/83J4f/Oy+P/zcrh/7u4zv+dm67/kI6e/5eVpP+SkKD/iIeV/2tqdv/KyN7/d3aD/7Wyx/+Eg4z/0tLS///////////////////////////////////////////////////////////////////////+/f3/z8/O/3Rxf/+RkJ//iomX/4aFk/+Yl6f/trTI/87M4P/Jx9v/wcDS/9/d9f/Ny+D/lJOj/3d2g/+ZmKn/zcvj/83L4v+cmqz/iYmN//r6+v///////////////////////////////////////////////////////////+jo6P+HhZL/z83h/9LP5P+1s8X/mJem/5WUof+XlqL/cnF7/1NTWv9hYWj/wsHT/+Dd9P+fna7/goCQ/87L4//Oy+T/zsvk/83L4/+opbn/4uLi/////////////////////////////////////////////////////////////v7+/6Sisf+HhpP/cXB5/29ueP9paHH/Z2Vu/2Zlbf9ubXb/YGBp/2dmbf+ZmKX/4N71/4yLmf+CgJD/zcvj/7680v+hoLD/zcvi/8K/1f/X19j////////////////////////////////////////////////////////////+/v7/j46b/5OSof9vbnX/W1pi/19eZf9YWF7/Wlpg/1BQVv9oaHL/jIuX/7q4y//f3fX/jo6c/5yaqv/Oy+P/xMHZ/52brf/Oy+P/w8DV/6ysrf////////////////////////////////////////////////////////////7//v+6ucT/vLnN/2tqdP+Vk6L/nJus/7Oxxf/Jxtv/s7DD/5eUpP+amKb/ioiU/9DO4/+Yl6b/eHaF/87L5P/Oy+P/zsvk/87L4//IxNz/tLS2/////////////////////////////////////////////////////////////////5aVnf+sq7z/fn2I/5+eqf9wbXX/SEtN/3aMgP9rinb/a4x3/2WgeP82bEL/y8rc/5GPnv+cmqv/zsvj/87L5P/Oy+T/zsvj/8/L5P+2tbn///////////////////////////////////////7+/v/CwsL/wMDA//7+/v/+/v7/tbS7/4eFlP9Va2D/KZtD/yeoRf8xzFX/Ms9W/zHRVv8x0Vb/MNFW/y3ETf+dnKv/q6q6/5KQoP+8us//zsvk/87L5P/Oy+P/z8vj/4uLj/////////////////////////////////////////////39/f/U1NT/mpqa//v8+/+Qj5P/o6Cy/0ZwVv8v0lb/MNFX/ymUPv8lhjf/MrZP/zDSVv8w0Vb/M85V/6Gsr/+lo7T/oZ+x/726z//Oy+T/zsvk/87L4//Oy+P/m5ug///////////////////////////////////////+/v7/v7+//6qqqv+YmJj/0tLS/62tr/+WlqX/U2ph/zDRVv8vyFL/H2gu/yOBNv8miDr/MdFX/zHRVv8z0Vj/c4KA/8jG2/+bmar/kpGh/87L4//Oy+T/zsvj/83L4/+ysbr///7+///////////////////////////////////////+/v7/sbGx/6Ghof/4+Pj/tra3/767zP9hcG//L9FW/zDRV/8w0lb/Mc9W/zHQV/8wx1L/Lr5Q/zLRV/94mof/zcvh/5KPoP+RkKD/zsvk/87L5P/Oy+T/zcvj/4+Ol//+/v7///////////////////////////////////////7+/v/l5eX///////////+4t7j/uLbH/1FQWv8zwFP/GVIk/zLRV/8w0lb/L9FW/yuqR/8ljT7/MdFW/1uLaP/g3fT/k5Gg/4B+jf/Oy+P/zsvk/87L5P/Oy+T/np6n///+/v///////////////////////////////////////////////////////////+Pj4/+6uMv/aWd0/zC5T/8yylb/MdFX/zHRV/8v0lX/NM9Y/zPGVf8vr03/XYlq/9/d9v+WlaT/ioiW/87L4//Oy+T/zsvk/87L5P+wr73////+///////////////////////////////////////////////////////+//7/4+Pj/6Sis/9mZHD/HWQv/ziRT/87fU7/Tn9g/01sWv9KU1T/VFlg/1xaZv+Rj57/3931/5KRoP+gnrH/zsvj/87L5P/Oy+T/zsvk/4SDkP/+/v3////////////////////////////////////////////////////////////8+/v/rau6/6yqu/+FhJH/gYGO/52bq/+Yl6X/rKq8/7Szw//AvtD/vLrM/5iWqP+amaj/Wlpj/5uaqv/Jxtz/zsvk/83L5P/Oy+P/hIKP//79/f////////////////////////////////////////////////////////////39/f9wcHn/o6Gy/5iXpv+VlKP/paOz/4eGk/+Xlqb/iIeX/6Kgs/+0ssb/yMbc/8zK4f/Oy+T/vbrP/4GAkP+Dgo//qKa4/6+uwf+Kio3///7//////////////////////////////////////////////////////////////v7+/7i4uP+Li4z/goGE/5uZpP+SkKH/tbLG/83K4//OyuP/uLXL/6Cerf+Zl6L/n56n/4+Omv+Ylqb/trTE/5aVoP9oZ2r/lZWW//39/f/////////////////////////////////////////////////////////////////////////////////+/v7//v7+//T09P+5ubn/o6Om/5OTmP+jo6f/vLy8//7+/v/+/v7/+fn4//b39v/+//7//f7+//7+/v////7////////////////////////////////////////////////////////////////////////////////////////////////////////////+/v7//v7+//7+/v////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAADAAAABgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+/v7//v79//7+/v/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+/v7/9vf3/+Li4//4+Pj////+//////////////////////////////////////////////////////////////////Hx8f/f39//39/f/8nJyf+srKv/l5eW/8PDw//9/f3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////v7+/+jp6P+trrD/np2l/4aFjf+cm5//8vLy/////////////////////////////////////////////////////////////v7+/5+fn/8hISH/ISEh/xwcHP8cHB7/GRkb/ygpKv++vr///v7+////////////////////////////////////////////////////////////////////////////////////////////+/v7/+zt7f/a2dv/r6+0/4GAjP+2tcf/0tDk/5KSnv+4tcX/u7rD/+zs7f/+/f7//////////////////////////////////////////////////v7+/5+gof9ISE//hoaU/6Gfsv/Oy+D/2Nbq/15dav9JSUn/4eHh/////////////////////////////////////////////////////////////////////////////////+rq6//CwsP/tLO5/7Cvuv+ko7H/p6S1/6Wksv97eob/cXF8/z09Qv93doD/rau6/4qKkP/n5+j////////////////////////////////////////////////////+/83Lz/+9vMv/3930/9/d9f/g3fX/4N31/728z/8pKS3/WFhZ/+Tk5P/+/v7///////////////////////////////////////////////////////39/f/Z2tr/lJWX/46MlP+zsr7/nJqp/359i/+lpLL/cG53/zg4PP8yMjf/VFNd/4SDjf9oZ2//YWFo/5qYpP+xsLf/8fLy/////////////////////////////////////////////v7+//Hx8f+oqK7/09Ll/+Dd9v/g3fX/4N32/9PR6P9aWWT/CQkK/0pKS//k5OX///7+//////////////////////////////////n5+f/o6On/0NDS/4aGi/+Jh5H/trPC/4qHlv95d4P/mJek/5eWov+DgYv/PT1C/3l4gf+Bf4n/ZGNq/1VVX/9xb3r/QUBH/1lYXv+KiZP/n5+j//Ly8f/+/v////////////////////////////////////////7+/v/MzM3/l5af/9DN4v/a2O7/zszh/83L3/+6uMn/X15o/x8fI/9tbWz/9fX1//////////////////v7+//c3Nz/vLy9/6qqrv+FhYz/hIKO/6OisP+WlaH/fn2G/3Jwe/9eXmX/PT1D/0dITv89PUP/T09S/2tqc/94d4H/dHR7/2Zmbf96eYL/fn2G/z8/RP98e4T/oqGu/6enrv/W1tf/8fHx/+fn5//09PT//v7+//7+/v/+/v7//v7+///////+/v7/zs7O/6OiqP+nprL/iomW/6Sjr/+dm6f/fHqF/319hP+Hh4n/9PT1///+///6+fr/y8zL/6moq/9/foP/Y2Nq/318h/+mpbL/iIeR/01NU/87O0H/OjpA/3p5gf9ZWF7/cnF5/5+eq/90c3//MTE2/z8+Q/97eoT/c3J7/1lZXv9lZGz/W1pi/4eFjv9DQ0j/ampz/727y/+XlZ//x8fH/76+v/+srKz/tra2/7Ozs/+ioqL/s7Oz//j4+P///////v7+//X19f/X2Nn/oaKn/35+hf+Af4P/gYGE/8rKy//w8PH//v7+/9/f3/+AgIP/kpGa/4aFkf+Oi5j/kI2a/3Jxef8vLzP/Ly4y/2BgZv+Cgon/bWx0/1hXYP+SkJz/hIOQ/1hXYP++vcr/bGt2/ycnKv9SUlb/WFdf/2tqcf9eXWP/d3eA/0RES/9qaW//TU1R/3V0fv+WlKH/yMjI//79/v/+/v7//v7+//7+/v/4+Pj/0dHR/5GRkf/ExMT/8fHx//Hx8f/x8vH/7e7u/8LCwv+bnJv/5ubm//7+/v///////////9fW1/9vbnP/bm11/2dlb/9TUln/Kywv/zs7Pv9OTVP/g4KL/4+Omv93dYD/hoSQ/4KBi/+CgYv/n52q/359h/+QkJv/a2tz/25td/80NDj/b253/21sdv9hYGj/bW10/4eGjv+IhpH/jYuX/6Oiq/+oqKr/9PT0//7//v//////////////////////4eHh/6ioqP+Wlpb/ysrK/9PU0//T1NP/zs/O/729vv/w8PD//f39//////////////////b29v+ko6T/MjI1/1FRV/9RUVn/op+u/2Jiav91dH3/Tk5V/5uap/9/fYj/WVhh/2JiZ/+ioKz/dXN+/21rdv+korH/ampy/8PBz/9xcHn/enqE/8G+zf+KiJP/d3Z8/56eo//S0tX/5ufp/+7u7//6+vr/////////////////////////////////urq6/+Xl5f+3t7f/1tbW//z8/P/8/Pz/+/v7/7u7u/+xsbH/zMzM//z8/P/////////////////9/f3/tre3/1lYXf+zsb//q6q3/11cZf+mpLL/bm11/39+if9qanP/gH+I/2Ria/9nZm//op+s/4aFj/+dnKf/hIOM/1pbYf+Hhor/lpec/56gn//P0M//9/f2//3+/P/9//7///7+///+/v//////////////////////////////////////y8vL/6mpqf/MzMz/r6+v/+/v7//i4uL/qamp/7m5uf/u7u7/r6+v/5WVlf/4+Pj//////////////////v7+/8HBwf+FhYn/kI6a/21sdP99fIb/YmFq/3Z2f/+Pj5r/bGtz/1NSWf96eIH/eHh+/3d4ev+cnJ7/tbS2/8HBwv/l5eX/+/v7//7//v///////////////////////////////////////////////////////////////////////v7+/9fX1/+1tbX/k5OT/5WVlf+Hh4f/x8fH/+vr6//a2tr/x8fH/6Ghof/29vb///////////////////////39/f/e3t//dHN2/1ZVW/9xcHn/p6Wx/1taYv9tbHX/U1JX/3p5fP+8vLz/3t7e/+zs7P/29vb//v79//////////////////////////////////////////////////z8/P/6+vr///////////////////////////////////////7+/v/19fX/7+/v/+jo6P/S0tL/zs7O/87Ozv/Pz8//5ubm//T09P/////////////////////////////////+//7/+Pj4/5qZmv97e33/XV1f/6Ojo//T09P/9vb2//7+/v/+/v7//v7+///+///+//7//v////39/v/7/Pz/7u/v/+zr7P/m5eb/5ufo/8XGx/+ysrX/d3d6/3p6gP9VVVj/vr6+//T09P///v7////+//////////////////////////////////39/f/+/v7////////////+/v7//v7+//////////////////////////////////////////////////7+/v/+/v7//v7+//7+/v/+/v7///////7+/v/+/v7/+fn5/+Pj4//S0tL/urq8/7Gxs/+fnqL/jIuR/42Mlf+Yl6L/oZ+u/5uZq/+npbn/tLLH/7a0yf9zcn3/fnyI/5GRl//IyMj/+fr5//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////7//v/29/f/wMDB/62trv9zc3X/dnV7/2RkbP+JiJT/nZus/7q4yv+5t8r/vrvS/8G/1//LyuH/zMri/87L5P/NyuL/yMXZ/7Wzxv+BgIz/xMHY/5COnP96eYP/j46Q//j4+P///v3////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+//b19f+HiIr/fn2L/5eWqP/KyNz/zcnh/83L4//Oy+P/zsvj/8vI4f/Cvtf/u7jP/7azxv+vrcD/rKu7/3h3hP9zcn7/SEhR/zc3Pv+IiJb/zMvf/0ZFT//Gw9j/i4mY/11dYf/Pz9D/+Pf4//////////////////////////////////////////////////////////////////////////////////////////////////////////////////X19f+Tk5f/u7nP/83L4v/Bv9b/u7nO/5SSpP+WlaT/iIeW/6WktP+Qj57/k5Ki/4iIl/+korT/uLbK/83L4f/X1ev/wr/S/35+iv/Cwdf/l5Wl/0NCS//Hxdz/zsvj/7m2y/+FhJH/l5eb/8nJyf/5+fn//////////////////////////////////////////////////////////////////////////////////////////////////Pz7/+Hh4P9vbnL/aGVz/19faf9tbXj/iIeT/6Gfrv+6ucv/xsTZ/9LP5v/U0en/2dfr/87M3/+nprX/srDA/+Dc9P/f3fX/wr/T/29vev+trMD/ZmVu/6Khsv/MyuL/zsvk/87L4//Ixt3/tLHG/3t6hf+hoqL//Pz8///////////////////////////////////////////////////////////////////////////////////////+/v7/y8zM/1ZWXf+hn67/0tDj/9rX7P/W0+n/0c7k/8XD2P/DwdP/trXE/5qZpf94d4D/SklR/1RUW/97eoX/Tk9V/7e1xf/f3fX/4Nz0/5SToP+rqL3/fnuK/87K5P/Oy+T/zsvk/87L5P/Oy+P/zcvk/7260f+Xl53/9fX1///////////////////////////////////////////////////////////////////////////////////////+/v7/9vb2/4+Nmf/e2/P/mZem/6Sisv+Mi5f/iIeR/0pJUf9mZm7/VlZd/4GAif+Mipb/hISN/19faP9cW2P/YGFm/5SSoP/g3fT/4N70/2Jhbf+npbj/fnuK/87L4//Oy+P/zsvj/8PB1//NyuL/zczj/8nF3v+5uML/9fX1/////////////////////////////////////////////////////////////////////////////////////////////f39/29ud//c2e//UVFY/1pZYP9xcHr/bWx2/4qJk/9paHL/Y2Jq/09PVf9zcnz/bW11/2JibP9eXmT/UlJY/1tbYv/e2/H/4N71/29uev+npbf/fnuK/83K4v/Oy+P/o6K1/4aFk/+yscP/zcvj/8rG3v+sq7X/7+/w/////////////////////////////////////////////////////////////////////////////////////////////f39/1lYX//d2vH/U1Jd/2dmbP93dn7/SEdP/3V0fP9NTFT/cXF3/2JiZv9dXWT/Q0NJ/1RUXP9oZm//dnZ9/3p5iP/e2/H/4N31/5GQn/+sqrz/h4WU/83L4v/Oy+P/uLfN/3p5hv+rqbz/zsvj/8rH3v+Ih5L/4uPj/////////////////////////////////////////////////////////////////////////////////////////////v7+/4WFi//g3fT/dXN+/0ZHSv9fXWX/SEdO/1FSWP9ZWWH/dXV//4+Nnf+bman/nJmp/6Kgsf/EwdT/vrzP/83K3//Fw9b/3dvz/4eHlP+dm6z/aGhz/87L5P/Ny+P/ycbe/8rI3//Oy+T/zsvj/8rH3/+Ih5L/4+Pk/////////////////////////////////////////////////////////////////////////////////////////////v7+/6iprf/U0ub/xsPY/5yaqv+pp7n/xMLW/8XD2P/PzeT/0c7k/9LP5f+fna3/j42c/1ZVX/9/fYn/cW95/4iGkf+Mi5b/2dfu/8G/0P+jobL/Q0JM/8/M4//Oy+T/zsvk/87L5P/Oy+T/zsvj/83K4v+fnav/6Ojp/////////////////////////////////////////////////////////////////////////////////////////////v///5aYmv+5t8v/tbXF/6KhsP+wr77/i4yW/2Riav9lZWz/TkxT/5GVmf+Pl5f/mqOi/5ympf+ntbP/fpCH/1BhVf9yeHr/2dbt/8LA1P+PjZ3/cnF+/8/M4//Oy+T/zsvk/87L5P/Oy+T/zsvj/87L5P+npbX/5+fo//////////////////////////////////////////////////////////////////X19f/19fX//v7+/////////////////6ipq/+3tMf/UVBY/1VUXv9VY1v/Zo1z/0JtTv9FhFb/OohN/z+eVv88rFb/KJlC/yaWQP8qqUj/KrdN/yuySf9YlWj/0c/k/8TC1v+RkJ//fXuI/7+90//Oy+T/zsvk/87L5P/Oy+T/zsvj/87L5P+Oi5v/0NDR/////////////////////////////////////////////////////////////v7+/8zMzP9ubm7/urq6//39/f///////v7+/9PT1f+3tcf/UVFb/2Fna/8umUT/LsJR/y3CT/8ty1L/Mc9W/zPPV/8x0Vb/MtBX/zDSVf8x0Vb/L9JV/y/MVP9CiVH/ycbd/8/N4v+iobH/bWt4/7Cvwf/Oy+T/zsvk/87L5P/Oy+T/zsvj/87L5P+Bf47/xsbH/////////////////////////////////////////////////////////////v7+//7+/v/x8fH/nZ2d/2lpaf/ExMT//f7+/8rJy/+PjZz/f3+N/1djZf8tqUr/L9JW/y/SVv8zy1T/Jok5/yJyMP8qlEH/Ms1V/y/SVv8v0lb/L9FW/zHQVv9Kn17/ysvd/8vK3v+HhZT/lZSk/7Kwwf/Oy+T/zsvk/87L5P/Oy+T/zsvk/87L5P+GhZP/yMjJ//////////////////////////////////////////////////////////////////Dw8P/V1dX/xMTE/5qamv+8vLz//P38/8rLy/+PjZv/amhz/2Zzdv8toUj/L9JW/y/QVf8nmUH/JHIy/zXRVf8eYSr/Koo//zHRV/8v0lb/MdFW/zHSVf87mFD/vsLQ/9HQ5P+Zl6b/r63C/5COnP/Oy+T/zsvk/87L5P/Oy+T/zsvi/87L4/+npbj/09PW/////v///v///////////////////////////////////////////////////v7+/7CwsP+vr6//xMTE/9TU1P+UlJT/5OXl/+Xl5v+vrbr/Z2Zy/3N6gv8niz//L9JW/y/PVf8rpUf/GVwm/x1iKv8khjj/LrxN/zHRVv8y0Vf/MNFW/y/SV/8ngjr/srTC/9fV7P+Qjp3/p6S5/2pqdP/Ny+P/zsvj/87L5P/Oy+T/zsvk/83L4/+tq7//xMTH///+//////////////////////////////////////////////////////////////7+/v/39/f/0dHR/29vb/+5ubn/+vv7/+jo5/+rqbX/sK6+/3Z6hf8ukEf/L9JW/y/SVv8u0lb/MdJW/zLKVv8w0Vf/MtBX/zHRVf8wyFP/MM5W/zLRV/8nkD3/sbnB/9fX7P+DgY//ubbM/359iv/Ny+L/zszj/87L4//Oy+T/zsvk/83L4/+rqb7/k5OW///+///+//7////////////////////////////////////////////////////////////U1NT/lpaW/+Xl5f/+/v7//v/+/+Pj4v+Rj5n/sK6+/2dodP9Ckln/Mc9W/yieQ/8wulD/L9JV/zHRV/8w0Vf/MNFV/zDDUP8cZiv/LrNO/zDRVv8srUj/mqqp/97a8v+bmqr/vbvQ/01MV//Ixdz/zsvk/87L5P/Oy+T/zsvk/83L4/+rqb7/k5OW///+/v/////////////////////////////////////////////////////////////////39/f/+fn5/////////////////+np6f+ioar/r62+/1ZUX/87fE//N8lX/w04FP8niz7/MtFX/zDSVv8v0lb/L9FW/zDIVf8nkj3/L79R/zDRVv8rrEb/fY2I/+De8/+Vk6P/tbPF/19dav/HxNr/zsvj/87L5P/Oy+T/zsvk/87L5P/AvtT/oaKn///+/v///v////////////////////////////////////////////////////////////////////////////////////////b19v/Av8j/yMba/2lodP9OiWP/MctT/zTFV/8yy1f/MdJV/zHRVv8v0lb/L9JV/zLRVv8y0Vj/MctW/y/GU/8tqkf/f5GK/9/d9v+WlKX/tLLF/4mGlf+0ssX/zsvk/87L5P/Oy+T/zsvk/87L5P/Ny+L/p6eu//////////7///////////////////////////////////////////////////////////////////////////////////////X19f+dnKL/zcvh/1BPWv9Se2L/MMJR/zDQVv8xxlP/McNT/zG6Uf8nmkH/MKBK/y2GQv81h0n/SYhd/0p4Wv9TemP/io+W/9/d9f+4tsr/r62+/4WElP+opbj/zsvk/87L5P/Oy+T/zsvk/87L5P/NyuL/cnF5//7+/v////7//////////////////////////////////////////////////////////////////////////////////v/+//X19f+YmJz/zMnf/29uef83QkD/G1Uo/zhvSP9BXk7/Q1lQ/2h7d/9lb3P/Y29w/2Nkb/9mZ3T/SUpU/0hGUP9vb3v/op+t/97d9v+6ucz/hYSR/7u5zv+3tMv/zcvj/87L5P/Oy+T/zsvk/87L5P/Ny+L/VFNa//39/f////7///////////////////////////////////////////////////////////////////////////////////////79/f+8u8D/0M3i/6imtv99for/YV9q/19eaf96eob/Xl1p/1paZP+GhZL/iIWU/4uLmP/Avs//x8bZ/8jG2v/Ny9//yMTc/8jH2f+YlqT/ZWRu/7a0x//Hxdz/zMri/87L5P/Oy+T/zcvk/87L4//OyuL/VFNb//39/P///v////////////////////////////////////////////////////////////////////////////////////////7+/v+ko6b/xMLU/93a8v/Kx9z/xMHV/7+9z//Lydv/z83g/6altP+qqbn/mZio/4WEkv+dnKz/jYuZ/5KQoP+hn7D/h4WU/5SSov+PjJ7/iIaX/4eGlP+GhZP/h4aV/7680P/MyeD/zcvj/83L4/+xrsH/Xl5j//7+/f///v////////////////////////////////////////////////////////////////////////////////////////7+/v+SkpP/ioqW/5KRn/9WVV//dXWA/3d2gv9vbnn/oJ6v/5mYp/+op7j/uLfK/7Oyxv+9u9L/vrvT/8G+1P/MyeD/y8nh/8zK4//Oy+T/zcrk/8rH3/+9us//p6W5/2Zncf9gX2v/p6a2/726zv9qanL/y8zM///+///////////////////////////////////////////////////////////////////////////////////////////////////V1dX/c3Nz/0xMTf9YWVr/bm10/6yot/+9us3/urfN/8PA1v/LyeD/zcrk/87L4//Oy+P/wr/V/7u5zP/BvtD/qae3/6imtv+urbz/tbTF/7m3y//Ewdb/x8PZ/7a0xv+GhY//UU9U/0tLTf++vr///v7+///////////////////////////////////////////////////////////////////////////////////////////////////////+/v7//v79//r6+f/g4OD/0dHR/7OztP+zs7b/nZ2h/4qJkP+Qjpr/nZur/5uZq/+bmqv/gH+L/1dXWv+zs7X/s7O0/7i4uP/Gx8f/np6g/52dof/Dw8b/zs7R/7/Bwv+wsLD/wcHB/+jo5//+/v7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////7////9/f3/+/v7/+vr6//h4eL/ubm7/6+vsf+vr7H/zs7Q/+Hh4f/4+Pf//v7///////////7//Pz8//v7+//+/v7///////7//////v///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////v7+//7+/v/+/v7//v7+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==`; 2 | 3 | function return_html_index(headlines_ul: string, sources_ul: string, hours: number): string { 4 | return ` 5 | 6 | Newsfeed | aaronsdevera.com 7 | 8 | 9 | 10 | 11 | 466 | 467 | 468 |
469 |
470 |
471 |

NewsFeed

472 |
473 |
474 |

475 |
476 |
477 |

toggle dark

478 |
479 |
480 |

481 |
482 |
483 | 484 |
485 |
    Sources in past ${hours} hours
486 |

487 |

488 |

489 |
    490 |
    491 |
    492 | 493 | 494 | 499 | 504 | 602 | 603 | 604 | 605 | ` 606 | } 607 | 608 | async function do_md5(s: string): Promise { 609 | const msgUint8 = new TextEncoder().encode(s) // encode as (utf-8) Uint8Array 610 | const hashBuffer = await crypto.subtle.digest('MD5', msgUint8) // hash the message 611 | const hashArray = Array.from(new Uint8Array(hashBuffer)) // convert buffer to byte array 612 | const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('') // convert bytes to hex string 613 | return hashHex; 614 | } 615 | 616 | async function do_sha256(s :string): Promise { 617 | const msgUint8 = new TextEncoder().encode(s); 618 | const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8); 619 | const hashArray = Array.from(new Uint8Array(hashBuffer)); 620 | const digest = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); 621 | return digest; 622 | } 623 | 624 | async function gen_uid(): Promise { 625 | const uuid = crypto.randomUUID(); 626 | return await do_md5(uuid); 627 | } 628 | 629 | async function gen_session(): Promise { 630 | const uuid1 = await gen_uid(); 631 | const uuid2 = await gen_uid(); 632 | return `${uuid1}${uuid2}`; 633 | } 634 | 635 | function gen_ts(): Number { 636 | //return Math.trunc((Date.now())/1000); 637 | return Date.now()/1000; 638 | } 639 | 640 | function gen_dt_from_ts(ts: any): Date { 641 | return new Date(ts*1000); 642 | } 643 | 644 | async function search(env: Env, auth_headers: Object, query: string = '*', size: number = 500): Promise { 645 | const url = `${env.DATA_SINK_URL}/search/newsfeed-headlines`; 646 | 647 | const body = { 648 | sort: [ 649 | { "created_at" : {"order" : "desc", "format": "date"}}, 650 | { "ingested_at" : {"order" : "desc", "format": "date"}} 651 | ], 652 | query: { 653 | query_string: { 654 | query: query 655 | } 656 | }, 657 | size: size 658 | } 659 | 660 | const resp = await fetch(url, { 661 | method: 'POST', 662 | headers: auth_headers, 663 | body: JSON.stringify(body) 664 | }); 665 | 666 | 667 | const json = await resp.json(); 668 | 669 | return json; 670 | } 671 | 672 | 673 | async function sql(env: Env, auth_headers: Object, query: string = '', size: number = 500): Promise { 674 | const url = `${env.DATA_SINK_URL}/sql`; 675 | 676 | const body = {query: query} 677 | 678 | const resp = await fetch(url, { 679 | method: 'POST', 680 | headers: auth_headers, 681 | body: JSON.stringify(body) 682 | }); 683 | 684 | 685 | const json = await resp.json(); 686 | 687 | return json; 688 | } 689 | 690 | async function get_headlines(env: Env, auth_headers: Object, source_name: string = '', source_type: string = '', size: number = 250, hours: number = 24): Promise { 691 | let resp: Promise; 692 | if (source_name !== '' && source_type === '') { 693 | resp = await search(env, auth_headers, `(created_at:>now-${hours}h) AND source_name:"${source_name}"`, size/2); 694 | } 695 | else if (source_name === '' && source_type !== '') { 696 | resp = await search(env, auth_headers, `(created_at:>now-${hours}h) AND source_type:"${source_type}"`, size-50); 697 | } 698 | else { 699 | resp = await search(env, auth_headers, `(created_at:>now-${hours}h)`, size); 700 | } 701 | const hits = resp.hits.hits; 702 | const headlines = []; 703 | for (const hit of hits) { 704 | headlines.push(hit._source); 705 | } 706 | return headlines; 707 | } 708 | 709 | async function get_sources(env: Env, auth_headers: Object, hours: number = 24): Promise { 710 | const resp = await sql(env, auth_headers, `select source_name, source_type, count(*) volume from "newsfeed-headlines" where created_at > now() - interval ${hours} hour group by 1,2 order by volume desc`); 711 | 712 | const rows = resp.rows; 713 | const sources = []; 714 | for (const row of rows) { 715 | sources.push({'source_name': row[0], 'source_type': row[1], 'volume': row[2]}); 716 | } 717 | return sources; 718 | } 719 | 720 | export default { 721 | async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { 722 | const url = new URL(request.url); 723 | const path = url.pathname; 724 | 725 | const default_hours = 48; 726 | 727 | 728 | let auth_headers = {}; 729 | auth_headers[env.AUTH_HEADER_ONE_KEY] = env.AUTH_HEADER_ONE_VALUE; 730 | auth_headers[env.AUTH_HEADER_TWO_KEY] = env.AUTH_HEADER_TWO_VALUE; 731 | 732 | const sources = await get_sources(env, auth_headers, default_hours); 733 | 734 | if (url.searchParams.get('source_name') !== null) { 735 | const source_name = url.searchParams.get('source_name'); 736 | const headlines = await get_headlines(env, auth_headers, source_name, '', 300, default_hours); 737 | return new Response( 738 | return_html_index(JSON.stringify(headlines), JSON.stringify(sources), default_hours), 739 | { 740 | status: 200, 741 | headers: { 742 | 'content-type': 'text/html', 743 | } 744 | } 745 | ); 746 | } 747 | 748 | if (url.searchParams.get('source_type') !== null) { 749 | const source_type = url.searchParams.get('source_type'); 750 | const headlines = await get_headlines(env, auth_headers,'',source_type); 751 | return new Response( 752 | return_html_index(JSON.stringify(headlines), JSON.stringify(sources), default_hours), 753 | { 754 | status: 200, 755 | headers: { 756 | 'content-type': 'text/html', 757 | } 758 | } 759 | ); 760 | } 761 | 762 | if (path.startsWith('/favicon.ico')) { 763 | return new Response(Uint8Array.from(atob(favicon_ico), c => c.charCodeAt(0)), { 764 | status: 200, 765 | headers: { 766 | "Content-Type": "image/x-icon" 767 | } 768 | }) 769 | } 770 | 771 | if (path === '/') { 772 | const headlines = await get_headlines(env, auth_headers); 773 | 774 | return new Response( 775 | return_html_index(JSON.stringify(headlines), JSON.stringify(sources), default_hours), 776 | { 777 | status: 200, 778 | headers: { 779 | 'content-type': 'text/html', 780 | } 781 | } 782 | ); 783 | } 784 | 785 | return new Response(null,{status: 200}); 786 | }, 787 | }; -------------------------------------------------------------------------------- /site/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chillmilk-c2", 3 | "version": "0.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "chillmilk-c2", 9 | "version": "0.0.0", 10 | "dependencies": { 11 | "ua-parser-js": "^1.0.37" 12 | }, 13 | "devDependencies": { 14 | "@cloudflare/workers-types": "^4.20230419.0", 15 | "itty-router": "^3.0.12", 16 | "typescript": "^5.0.4", 17 | "wrangler": "^3.0.0" 18 | } 19 | }, 20 | "node_modules/@cloudflare/kv-asset-handler": { 21 | "version": "0.2.0", 22 | "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.2.0.tgz", 23 | "integrity": "sha512-MVbXLbTcAotOPUj0pAMhVtJ+3/kFkwJqc5qNOleOZTv6QkZZABDMS21dSrSlVswEHwrpWC03e4fWytjqKvuE2A==", 24 | "dev": true, 25 | "dependencies": { 26 | "mime": "^3.0.0" 27 | } 28 | }, 29 | "node_modules/@cloudflare/workerd-darwin-64": { 30 | "version": "1.20231030.0", 31 | "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20231030.0.tgz", 32 | "integrity": "sha512-J4PQ9utPxLya9yHdMMx3AZeC5M/6FxcoYw6jo9jbDDFTy+a4Gslqf4Im9We3aeOEdPXa3tgQHVQOSelJSZLhIw==", 33 | "cpu": [ 34 | "x64" 35 | ], 36 | "dev": true, 37 | "optional": true, 38 | "os": [ 39 | "darwin" 40 | ], 41 | "engines": { 42 | "node": ">=16" 43 | } 44 | }, 45 | "node_modules/@cloudflare/workerd-darwin-arm64": { 46 | "version": "1.20231030.0", 47 | "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20231030.0.tgz", 48 | "integrity": "sha512-WSJJjm11Del4hSneiNB7wTXGtBXI4QMCH9l5qf4iT5PAW8cESGcCmdHtWDWDtGAAGcvmLT04KNvmum92vRKKQQ==", 49 | "cpu": [ 50 | "arm64" 51 | ], 52 | "dev": true, 53 | "optional": true, 54 | "os": [ 55 | "darwin" 56 | ], 57 | "engines": { 58 | "node": ">=16" 59 | } 60 | }, 61 | "node_modules/@cloudflare/workerd-linux-64": { 62 | "version": "1.20231030.0", 63 | "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20231030.0.tgz", 64 | "integrity": "sha512-2HUeRTvoCC17fxE0qdBeR7J9dO8j4A8ZbdcvY8pZxdk+zERU6+N03RTbk/dQMU488PwiDvcC3zZqS4gwLfVT8g==", 65 | "cpu": [ 66 | "x64" 67 | ], 68 | "dev": true, 69 | "optional": true, 70 | "os": [ 71 | "linux" 72 | ], 73 | "engines": { 74 | "node": ">=16" 75 | } 76 | }, 77 | "node_modules/@cloudflare/workerd-linux-arm64": { 78 | "version": "1.20231030.0", 79 | "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20231030.0.tgz", 80 | "integrity": "sha512-4/GK5zHh+9JbUI6Z5xTCM0ZmpKKHk7vu9thmHjUxtz+o8Ne9DoD7DlDvXQWgMF6XGaTubDWyp3ttn+Qv8jDFuQ==", 81 | "cpu": [ 82 | "arm64" 83 | ], 84 | "dev": true, 85 | "optional": true, 86 | "os": [ 87 | "linux" 88 | ], 89 | "engines": { 90 | "node": ">=16" 91 | } 92 | }, 93 | "node_modules/@cloudflare/workerd-windows-64": { 94 | "version": "1.20231030.0", 95 | "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20231030.0.tgz", 96 | "integrity": "sha512-fb/Jgj8Yqy3PO1jLhk7mTrHMkR8jklpbQFud6rL/aMAn5d6MQbaSrYOCjzkKGp0Zng8D2LIzSl+Fc0C9Sggxjg==", 97 | "cpu": [ 98 | "x64" 99 | ], 100 | "dev": true, 101 | "optional": true, 102 | "os": [ 103 | "win32" 104 | ], 105 | "engines": { 106 | "node": ">=16" 107 | } 108 | }, 109 | "node_modules/@cloudflare/workers-types": { 110 | "version": "4.20231121.0", 111 | "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20231121.0.tgz", 112 | "integrity": "sha512-+kWfpCkqiepwAKXyHoE0gnkPgkLhz0/9HOBIGhHRsUvUKvhUtm3mbqqoGRWgF1qcjzrDUBbrrOq4MYHfFtc2RA==", 113 | "dev": true 114 | }, 115 | "node_modules/@esbuild-plugins/node-globals-polyfill": { 116 | "version": "0.2.3", 117 | "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz", 118 | "integrity": "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==", 119 | "dev": true, 120 | "peerDependencies": { 121 | "esbuild": "*" 122 | } 123 | }, 124 | "node_modules/@esbuild-plugins/node-modules-polyfill": { 125 | "version": "0.2.2", 126 | "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.2.2.tgz", 127 | "integrity": "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==", 128 | "dev": true, 129 | "dependencies": { 130 | "escape-string-regexp": "^4.0.0", 131 | "rollup-plugin-node-polyfills": "^0.2.1" 132 | }, 133 | "peerDependencies": { 134 | "esbuild": "*" 135 | } 136 | }, 137 | "node_modules/@esbuild/android-arm": { 138 | "version": "0.17.19", 139 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", 140 | "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", 141 | "cpu": [ 142 | "arm" 143 | ], 144 | "dev": true, 145 | "optional": true, 146 | "os": [ 147 | "android" 148 | ], 149 | "engines": { 150 | "node": ">=12" 151 | } 152 | }, 153 | "node_modules/@esbuild/android-arm64": { 154 | "version": "0.17.19", 155 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", 156 | "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", 157 | "cpu": [ 158 | "arm64" 159 | ], 160 | "dev": true, 161 | "optional": true, 162 | "os": [ 163 | "android" 164 | ], 165 | "engines": { 166 | "node": ">=12" 167 | } 168 | }, 169 | "node_modules/@esbuild/android-x64": { 170 | "version": "0.17.19", 171 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", 172 | "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", 173 | "cpu": [ 174 | "x64" 175 | ], 176 | "dev": true, 177 | "optional": true, 178 | "os": [ 179 | "android" 180 | ], 181 | "engines": { 182 | "node": ">=12" 183 | } 184 | }, 185 | "node_modules/@esbuild/darwin-arm64": { 186 | "version": "0.17.19", 187 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", 188 | "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", 189 | "cpu": [ 190 | "arm64" 191 | ], 192 | "dev": true, 193 | "optional": true, 194 | "os": [ 195 | "darwin" 196 | ], 197 | "engines": { 198 | "node": ">=12" 199 | } 200 | }, 201 | "node_modules/@esbuild/darwin-x64": { 202 | "version": "0.17.19", 203 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", 204 | "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", 205 | "cpu": [ 206 | "x64" 207 | ], 208 | "dev": true, 209 | "optional": true, 210 | "os": [ 211 | "darwin" 212 | ], 213 | "engines": { 214 | "node": ">=12" 215 | } 216 | }, 217 | "node_modules/@esbuild/freebsd-arm64": { 218 | "version": "0.17.19", 219 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", 220 | "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", 221 | "cpu": [ 222 | "arm64" 223 | ], 224 | "dev": true, 225 | "optional": true, 226 | "os": [ 227 | "freebsd" 228 | ], 229 | "engines": { 230 | "node": ">=12" 231 | } 232 | }, 233 | "node_modules/@esbuild/freebsd-x64": { 234 | "version": "0.17.19", 235 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", 236 | "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", 237 | "cpu": [ 238 | "x64" 239 | ], 240 | "dev": true, 241 | "optional": true, 242 | "os": [ 243 | "freebsd" 244 | ], 245 | "engines": { 246 | "node": ">=12" 247 | } 248 | }, 249 | "node_modules/@esbuild/linux-arm": { 250 | "version": "0.17.19", 251 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", 252 | "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", 253 | "cpu": [ 254 | "arm" 255 | ], 256 | "dev": true, 257 | "optional": true, 258 | "os": [ 259 | "linux" 260 | ], 261 | "engines": { 262 | "node": ">=12" 263 | } 264 | }, 265 | "node_modules/@esbuild/linux-arm64": { 266 | "version": "0.17.19", 267 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", 268 | "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", 269 | "cpu": [ 270 | "arm64" 271 | ], 272 | "dev": true, 273 | "optional": true, 274 | "os": [ 275 | "linux" 276 | ], 277 | "engines": { 278 | "node": ">=12" 279 | } 280 | }, 281 | "node_modules/@esbuild/linux-ia32": { 282 | "version": "0.17.19", 283 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", 284 | "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", 285 | "cpu": [ 286 | "ia32" 287 | ], 288 | "dev": true, 289 | "optional": true, 290 | "os": [ 291 | "linux" 292 | ], 293 | "engines": { 294 | "node": ">=12" 295 | } 296 | }, 297 | "node_modules/@esbuild/linux-loong64": { 298 | "version": "0.17.19", 299 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", 300 | "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", 301 | "cpu": [ 302 | "loong64" 303 | ], 304 | "dev": true, 305 | "optional": true, 306 | "os": [ 307 | "linux" 308 | ], 309 | "engines": { 310 | "node": ">=12" 311 | } 312 | }, 313 | "node_modules/@esbuild/linux-mips64el": { 314 | "version": "0.17.19", 315 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", 316 | "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", 317 | "cpu": [ 318 | "mips64el" 319 | ], 320 | "dev": true, 321 | "optional": true, 322 | "os": [ 323 | "linux" 324 | ], 325 | "engines": { 326 | "node": ">=12" 327 | } 328 | }, 329 | "node_modules/@esbuild/linux-ppc64": { 330 | "version": "0.17.19", 331 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", 332 | "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", 333 | "cpu": [ 334 | "ppc64" 335 | ], 336 | "dev": true, 337 | "optional": true, 338 | "os": [ 339 | "linux" 340 | ], 341 | "engines": { 342 | "node": ">=12" 343 | } 344 | }, 345 | "node_modules/@esbuild/linux-riscv64": { 346 | "version": "0.17.19", 347 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", 348 | "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", 349 | "cpu": [ 350 | "riscv64" 351 | ], 352 | "dev": true, 353 | "optional": true, 354 | "os": [ 355 | "linux" 356 | ], 357 | "engines": { 358 | "node": ">=12" 359 | } 360 | }, 361 | "node_modules/@esbuild/linux-s390x": { 362 | "version": "0.17.19", 363 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", 364 | "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", 365 | "cpu": [ 366 | "s390x" 367 | ], 368 | "dev": true, 369 | "optional": true, 370 | "os": [ 371 | "linux" 372 | ], 373 | "engines": { 374 | "node": ">=12" 375 | } 376 | }, 377 | "node_modules/@esbuild/linux-x64": { 378 | "version": "0.17.19", 379 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", 380 | "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", 381 | "cpu": [ 382 | "x64" 383 | ], 384 | "dev": true, 385 | "optional": true, 386 | "os": [ 387 | "linux" 388 | ], 389 | "engines": { 390 | "node": ">=12" 391 | } 392 | }, 393 | "node_modules/@esbuild/netbsd-x64": { 394 | "version": "0.17.19", 395 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", 396 | "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", 397 | "cpu": [ 398 | "x64" 399 | ], 400 | "dev": true, 401 | "optional": true, 402 | "os": [ 403 | "netbsd" 404 | ], 405 | "engines": { 406 | "node": ">=12" 407 | } 408 | }, 409 | "node_modules/@esbuild/openbsd-x64": { 410 | "version": "0.17.19", 411 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", 412 | "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", 413 | "cpu": [ 414 | "x64" 415 | ], 416 | "dev": true, 417 | "optional": true, 418 | "os": [ 419 | "openbsd" 420 | ], 421 | "engines": { 422 | "node": ">=12" 423 | } 424 | }, 425 | "node_modules/@esbuild/sunos-x64": { 426 | "version": "0.17.19", 427 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", 428 | "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", 429 | "cpu": [ 430 | "x64" 431 | ], 432 | "dev": true, 433 | "optional": true, 434 | "os": [ 435 | "sunos" 436 | ], 437 | "engines": { 438 | "node": ">=12" 439 | } 440 | }, 441 | "node_modules/@esbuild/win32-arm64": { 442 | "version": "0.17.19", 443 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", 444 | "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", 445 | "cpu": [ 446 | "arm64" 447 | ], 448 | "dev": true, 449 | "optional": true, 450 | "os": [ 451 | "win32" 452 | ], 453 | "engines": { 454 | "node": ">=12" 455 | } 456 | }, 457 | "node_modules/@esbuild/win32-ia32": { 458 | "version": "0.17.19", 459 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", 460 | "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", 461 | "cpu": [ 462 | "ia32" 463 | ], 464 | "dev": true, 465 | "optional": true, 466 | "os": [ 467 | "win32" 468 | ], 469 | "engines": { 470 | "node": ">=12" 471 | } 472 | }, 473 | "node_modules/@esbuild/win32-x64": { 474 | "version": "0.17.19", 475 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", 476 | "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", 477 | "cpu": [ 478 | "x64" 479 | ], 480 | "dev": true, 481 | "optional": true, 482 | "os": [ 483 | "win32" 484 | ], 485 | "engines": { 486 | "node": ">=12" 487 | } 488 | }, 489 | "node_modules/@fastify/busboy": { 490 | "version": "2.1.0", 491 | "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", 492 | "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", 493 | "dev": true, 494 | "engines": { 495 | "node": ">=14" 496 | } 497 | }, 498 | "node_modules/@types/node": { 499 | "version": "20.9.4", 500 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.4.tgz", 501 | "integrity": "sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA==", 502 | "dev": true, 503 | "dependencies": { 504 | "undici-types": "~5.26.4" 505 | } 506 | }, 507 | "node_modules/@types/node-forge": { 508 | "version": "1.3.10", 509 | "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.10.tgz", 510 | "integrity": "sha512-y6PJDYN4xYBxwd22l+OVH35N+1fCYWiuC3aiP2SlXVE6Lo7SS+rSx9r89hLxrP4pn6n1lBGhHJ12pj3F3Mpttw==", 511 | "dev": true, 512 | "dependencies": { 513 | "@types/node": "*" 514 | } 515 | }, 516 | "node_modules/acorn": { 517 | "version": "8.11.2", 518 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", 519 | "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", 520 | "dev": true, 521 | "bin": { 522 | "acorn": "bin/acorn" 523 | }, 524 | "engines": { 525 | "node": ">=0.4.0" 526 | } 527 | }, 528 | "node_modules/acorn-walk": { 529 | "version": "8.3.0", 530 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", 531 | "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", 532 | "dev": true, 533 | "engines": { 534 | "node": ">=0.4.0" 535 | } 536 | }, 537 | "node_modules/anymatch": { 538 | "version": "3.1.3", 539 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 540 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 541 | "dev": true, 542 | "dependencies": { 543 | "normalize-path": "^3.0.0", 544 | "picomatch": "^2.0.4" 545 | }, 546 | "engines": { 547 | "node": ">= 8" 548 | } 549 | }, 550 | "node_modules/as-table": { 551 | "version": "1.0.55", 552 | "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", 553 | "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", 554 | "dev": true, 555 | "dependencies": { 556 | "printable-characters": "^1.0.42" 557 | } 558 | }, 559 | "node_modules/binary-extensions": { 560 | "version": "2.2.0", 561 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 562 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 563 | "dev": true, 564 | "engines": { 565 | "node": ">=8" 566 | } 567 | }, 568 | "node_modules/blake3-wasm": { 569 | "version": "2.1.5", 570 | "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", 571 | "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", 572 | "dev": true 573 | }, 574 | "node_modules/braces": { 575 | "version": "3.0.2", 576 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 577 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 578 | "dev": true, 579 | "dependencies": { 580 | "fill-range": "^7.0.1" 581 | }, 582 | "engines": { 583 | "node": ">=8" 584 | } 585 | }, 586 | "node_modules/buffer-from": { 587 | "version": "1.1.2", 588 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 589 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 590 | "dev": true 591 | }, 592 | "node_modules/capnp-ts": { 593 | "version": "0.7.0", 594 | "resolved": "https://registry.npmjs.org/capnp-ts/-/capnp-ts-0.7.0.tgz", 595 | "integrity": "sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==", 596 | "dev": true, 597 | "dependencies": { 598 | "debug": "^4.3.1", 599 | "tslib": "^2.2.0" 600 | } 601 | }, 602 | "node_modules/chokidar": { 603 | "version": "3.5.3", 604 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 605 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 606 | "dev": true, 607 | "funding": [ 608 | { 609 | "type": "individual", 610 | "url": "https://paulmillr.com/funding/" 611 | } 612 | ], 613 | "dependencies": { 614 | "anymatch": "~3.1.2", 615 | "braces": "~3.0.2", 616 | "glob-parent": "~5.1.2", 617 | "is-binary-path": "~2.1.0", 618 | "is-glob": "~4.0.1", 619 | "normalize-path": "~3.0.0", 620 | "readdirp": "~3.6.0" 621 | }, 622 | "engines": { 623 | "node": ">= 8.10.0" 624 | }, 625 | "optionalDependencies": { 626 | "fsevents": "~2.3.2" 627 | } 628 | }, 629 | "node_modules/cookie": { 630 | "version": "0.5.0", 631 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 632 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 633 | "dev": true, 634 | "engines": { 635 | "node": ">= 0.6" 636 | } 637 | }, 638 | "node_modules/data-uri-to-buffer": { 639 | "version": "2.0.2", 640 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", 641 | "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", 642 | "dev": true 643 | }, 644 | "node_modules/debug": { 645 | "version": "4.3.4", 646 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 647 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 648 | "dev": true, 649 | "dependencies": { 650 | "ms": "2.1.2" 651 | }, 652 | "engines": { 653 | "node": ">=6.0" 654 | }, 655 | "peerDependenciesMeta": { 656 | "supports-color": { 657 | "optional": true 658 | } 659 | } 660 | }, 661 | "node_modules/esbuild": { 662 | "version": "0.17.19", 663 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", 664 | "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", 665 | "dev": true, 666 | "hasInstallScript": true, 667 | "bin": { 668 | "esbuild": "bin/esbuild" 669 | }, 670 | "engines": { 671 | "node": ">=12" 672 | }, 673 | "optionalDependencies": { 674 | "@esbuild/android-arm": "0.17.19", 675 | "@esbuild/android-arm64": "0.17.19", 676 | "@esbuild/android-x64": "0.17.19", 677 | "@esbuild/darwin-arm64": "0.17.19", 678 | "@esbuild/darwin-x64": "0.17.19", 679 | "@esbuild/freebsd-arm64": "0.17.19", 680 | "@esbuild/freebsd-x64": "0.17.19", 681 | "@esbuild/linux-arm": "0.17.19", 682 | "@esbuild/linux-arm64": "0.17.19", 683 | "@esbuild/linux-ia32": "0.17.19", 684 | "@esbuild/linux-loong64": "0.17.19", 685 | "@esbuild/linux-mips64el": "0.17.19", 686 | "@esbuild/linux-ppc64": "0.17.19", 687 | "@esbuild/linux-riscv64": "0.17.19", 688 | "@esbuild/linux-s390x": "0.17.19", 689 | "@esbuild/linux-x64": "0.17.19", 690 | "@esbuild/netbsd-x64": "0.17.19", 691 | "@esbuild/openbsd-x64": "0.17.19", 692 | "@esbuild/sunos-x64": "0.17.19", 693 | "@esbuild/win32-arm64": "0.17.19", 694 | "@esbuild/win32-ia32": "0.17.19", 695 | "@esbuild/win32-x64": "0.17.19" 696 | } 697 | }, 698 | "node_modules/escape-string-regexp": { 699 | "version": "4.0.0", 700 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 701 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 702 | "dev": true, 703 | "engines": { 704 | "node": ">=10" 705 | }, 706 | "funding": { 707 | "url": "https://github.com/sponsors/sindresorhus" 708 | } 709 | }, 710 | "node_modules/estree-walker": { 711 | "version": "0.6.1", 712 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", 713 | "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", 714 | "dev": true 715 | }, 716 | "node_modules/exit-hook": { 717 | "version": "2.2.1", 718 | "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", 719 | "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", 720 | "dev": true, 721 | "engines": { 722 | "node": ">=6" 723 | }, 724 | "funding": { 725 | "url": "https://github.com/sponsors/sindresorhus" 726 | } 727 | }, 728 | "node_modules/fill-range": { 729 | "version": "7.0.1", 730 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 731 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 732 | "dev": true, 733 | "dependencies": { 734 | "to-regex-range": "^5.0.1" 735 | }, 736 | "engines": { 737 | "node": ">=8" 738 | } 739 | }, 740 | "node_modules/fsevents": { 741 | "version": "2.3.3", 742 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 743 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 744 | "dev": true, 745 | "hasInstallScript": true, 746 | "optional": true, 747 | "os": [ 748 | "darwin" 749 | ], 750 | "engines": { 751 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 752 | } 753 | }, 754 | "node_modules/get-source": { 755 | "version": "2.0.12", 756 | "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", 757 | "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", 758 | "dev": true, 759 | "dependencies": { 760 | "data-uri-to-buffer": "^2.0.0", 761 | "source-map": "^0.6.1" 762 | } 763 | }, 764 | "node_modules/glob-parent": { 765 | "version": "5.1.2", 766 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 767 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 768 | "dev": true, 769 | "dependencies": { 770 | "is-glob": "^4.0.1" 771 | }, 772 | "engines": { 773 | "node": ">= 6" 774 | } 775 | }, 776 | "node_modules/glob-to-regexp": { 777 | "version": "0.4.1", 778 | "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", 779 | "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", 780 | "dev": true 781 | }, 782 | "node_modules/is-binary-path": { 783 | "version": "2.1.0", 784 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 785 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 786 | "dev": true, 787 | "dependencies": { 788 | "binary-extensions": "^2.0.0" 789 | }, 790 | "engines": { 791 | "node": ">=8" 792 | } 793 | }, 794 | "node_modules/is-extglob": { 795 | "version": "2.1.1", 796 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 797 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 798 | "dev": true, 799 | "engines": { 800 | "node": ">=0.10.0" 801 | } 802 | }, 803 | "node_modules/is-glob": { 804 | "version": "4.0.3", 805 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 806 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 807 | "dev": true, 808 | "dependencies": { 809 | "is-extglob": "^2.1.1" 810 | }, 811 | "engines": { 812 | "node": ">=0.10.0" 813 | } 814 | }, 815 | "node_modules/is-number": { 816 | "version": "7.0.0", 817 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 818 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 819 | "dev": true, 820 | "engines": { 821 | "node": ">=0.12.0" 822 | } 823 | }, 824 | "node_modules/itty-router": { 825 | "version": "3.0.12", 826 | "resolved": "https://registry.npmjs.org/itty-router/-/itty-router-3.0.12.tgz", 827 | "integrity": "sha512-s98XTPhle6GGbaFf0kYrOD3Q8gyhnqvOqkwYijC3AmkceNKqWUp13YHg6dWmqmVv4pP7l7c94XI92I0EXVGO0w==", 828 | "dev": true 829 | }, 830 | "node_modules/magic-string": { 831 | "version": "0.25.9", 832 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", 833 | "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", 834 | "dev": true, 835 | "dependencies": { 836 | "sourcemap-codec": "^1.4.8" 837 | } 838 | }, 839 | "node_modules/mime": { 840 | "version": "3.0.0", 841 | "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", 842 | "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", 843 | "dev": true, 844 | "bin": { 845 | "mime": "cli.js" 846 | }, 847 | "engines": { 848 | "node": ">=10.0.0" 849 | } 850 | }, 851 | "node_modules/miniflare": { 852 | "version": "3.20231030.1", 853 | "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20231030.1.tgz", 854 | "integrity": "sha512-Y+EkgV/aFg/3Y/xfFtImK36sLZGXvNS45avVEz0cUCA2pGpg4hGdPu1Udmz5b06SyeUEFVf/dEDMJwdRYVEgLw==", 855 | "dev": true, 856 | "dependencies": { 857 | "acorn": "^8.8.0", 858 | "acorn-walk": "^8.2.0", 859 | "capnp-ts": "^0.7.0", 860 | "exit-hook": "^2.2.1", 861 | "glob-to-regexp": "^0.4.1", 862 | "source-map-support": "0.5.21", 863 | "stoppable": "^1.1.0", 864 | "undici": "^5.22.1", 865 | "workerd": "1.20231030.0", 866 | "ws": "^8.11.0", 867 | "youch": "^3.2.2", 868 | "zod": "^3.20.6" 869 | }, 870 | "bin": { 871 | "miniflare": "bootstrap.js" 872 | }, 873 | "engines": { 874 | "node": ">=16.13" 875 | } 876 | }, 877 | "node_modules/ms": { 878 | "version": "2.1.2", 879 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 880 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 881 | "dev": true 882 | }, 883 | "node_modules/mustache": { 884 | "version": "4.2.0", 885 | "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", 886 | "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", 887 | "dev": true, 888 | "bin": { 889 | "mustache": "bin/mustache" 890 | } 891 | }, 892 | "node_modules/nanoid": { 893 | "version": "3.3.7", 894 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 895 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 896 | "dev": true, 897 | "funding": [ 898 | { 899 | "type": "github", 900 | "url": "https://github.com/sponsors/ai" 901 | } 902 | ], 903 | "bin": { 904 | "nanoid": "bin/nanoid.cjs" 905 | }, 906 | "engines": { 907 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 908 | } 909 | }, 910 | "node_modules/node-forge": { 911 | "version": "1.3.1", 912 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", 913 | "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", 914 | "dev": true, 915 | "engines": { 916 | "node": ">= 6.13.0" 917 | } 918 | }, 919 | "node_modules/normalize-path": { 920 | "version": "3.0.0", 921 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 922 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 923 | "dev": true, 924 | "engines": { 925 | "node": ">=0.10.0" 926 | } 927 | }, 928 | "node_modules/path-to-regexp": { 929 | "version": "6.2.1", 930 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", 931 | "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", 932 | "dev": true 933 | }, 934 | "node_modules/picomatch": { 935 | "version": "2.3.1", 936 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 937 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 938 | "dev": true, 939 | "engines": { 940 | "node": ">=8.6" 941 | }, 942 | "funding": { 943 | "url": "https://github.com/sponsors/jonschlinkert" 944 | } 945 | }, 946 | "node_modules/printable-characters": { 947 | "version": "1.0.42", 948 | "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", 949 | "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", 950 | "dev": true 951 | }, 952 | "node_modules/readdirp": { 953 | "version": "3.6.0", 954 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 955 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 956 | "dev": true, 957 | "dependencies": { 958 | "picomatch": "^2.2.1" 959 | }, 960 | "engines": { 961 | "node": ">=8.10.0" 962 | } 963 | }, 964 | "node_modules/resolve.exports": { 965 | "version": "2.0.2", 966 | "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", 967 | "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", 968 | "dev": true, 969 | "engines": { 970 | "node": ">=10" 971 | } 972 | }, 973 | "node_modules/rollup-plugin-inject": { 974 | "version": "3.0.2", 975 | "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", 976 | "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", 977 | "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.", 978 | "dev": true, 979 | "dependencies": { 980 | "estree-walker": "^0.6.1", 981 | "magic-string": "^0.25.3", 982 | "rollup-pluginutils": "^2.8.1" 983 | } 984 | }, 985 | "node_modules/rollup-plugin-node-polyfills": { 986 | "version": "0.2.1", 987 | "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", 988 | "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", 989 | "dev": true, 990 | "dependencies": { 991 | "rollup-plugin-inject": "^3.0.0" 992 | } 993 | }, 994 | "node_modules/rollup-pluginutils": { 995 | "version": "2.8.2", 996 | "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", 997 | "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", 998 | "dev": true, 999 | "dependencies": { 1000 | "estree-walker": "^0.6.1" 1001 | } 1002 | }, 1003 | "node_modules/selfsigned": { 1004 | "version": "2.4.1", 1005 | "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", 1006 | "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", 1007 | "dev": true, 1008 | "dependencies": { 1009 | "@types/node-forge": "^1.3.0", 1010 | "node-forge": "^1" 1011 | }, 1012 | "engines": { 1013 | "node": ">=10" 1014 | } 1015 | }, 1016 | "node_modules/source-map": { 1017 | "version": "0.6.1", 1018 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1019 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1020 | "dev": true, 1021 | "engines": { 1022 | "node": ">=0.10.0" 1023 | } 1024 | }, 1025 | "node_modules/source-map-support": { 1026 | "version": "0.5.21", 1027 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", 1028 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 1029 | "dev": true, 1030 | "dependencies": { 1031 | "buffer-from": "^1.0.0", 1032 | "source-map": "^0.6.0" 1033 | } 1034 | }, 1035 | "node_modules/sourcemap-codec": { 1036 | "version": "1.4.8", 1037 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 1038 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 1039 | "deprecated": "Please use @jridgewell/sourcemap-codec instead", 1040 | "dev": true 1041 | }, 1042 | "node_modules/stacktracey": { 1043 | "version": "2.1.8", 1044 | "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", 1045 | "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==", 1046 | "dev": true, 1047 | "dependencies": { 1048 | "as-table": "^1.0.36", 1049 | "get-source": "^2.0.12" 1050 | } 1051 | }, 1052 | "node_modules/stoppable": { 1053 | "version": "1.1.0", 1054 | "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", 1055 | "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", 1056 | "dev": true, 1057 | "engines": { 1058 | "node": ">=4", 1059 | "npm": ">=6" 1060 | } 1061 | }, 1062 | "node_modules/to-regex-range": { 1063 | "version": "5.0.1", 1064 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1065 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1066 | "dev": true, 1067 | "dependencies": { 1068 | "is-number": "^7.0.0" 1069 | }, 1070 | "engines": { 1071 | "node": ">=8.0" 1072 | } 1073 | }, 1074 | "node_modules/tslib": { 1075 | "version": "2.6.2", 1076 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", 1077 | "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", 1078 | "dev": true 1079 | }, 1080 | "node_modules/typescript": { 1081 | "version": "5.3.2", 1082 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", 1083 | "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", 1084 | "dev": true, 1085 | "bin": { 1086 | "tsc": "bin/tsc", 1087 | "tsserver": "bin/tsserver" 1088 | }, 1089 | "engines": { 1090 | "node": ">=14.17" 1091 | } 1092 | }, 1093 | "node_modules/ua-parser-js": { 1094 | "version": "1.0.37", 1095 | "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", 1096 | "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", 1097 | "funding": [ 1098 | { 1099 | "type": "opencollective", 1100 | "url": "https://opencollective.com/ua-parser-js" 1101 | }, 1102 | { 1103 | "type": "paypal", 1104 | "url": "https://paypal.me/faisalman" 1105 | }, 1106 | { 1107 | "type": "github", 1108 | "url": "https://github.com/sponsors/faisalman" 1109 | } 1110 | ], 1111 | "engines": { 1112 | "node": "*" 1113 | } 1114 | }, 1115 | "node_modules/undici": { 1116 | "version": "5.27.2", 1117 | "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz", 1118 | "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==", 1119 | "dev": true, 1120 | "dependencies": { 1121 | "@fastify/busboy": "^2.0.0" 1122 | }, 1123 | "engines": { 1124 | "node": ">=14.0" 1125 | } 1126 | }, 1127 | "node_modules/undici-types": { 1128 | "version": "5.26.5", 1129 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 1130 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 1131 | "dev": true 1132 | }, 1133 | "node_modules/workerd": { 1134 | "version": "1.20231030.0", 1135 | "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20231030.0.tgz", 1136 | "integrity": "sha512-+FSW+d31f8RrjHanFf/R9A+Z0csf3OtsvzdPmAKuwuZm/5HrBv83cvG9fFeTxl7/nI6irUUXIRF9xcj/NomQzQ==", 1137 | "dev": true, 1138 | "hasInstallScript": true, 1139 | "bin": { 1140 | "workerd": "bin/workerd" 1141 | }, 1142 | "engines": { 1143 | "node": ">=16" 1144 | }, 1145 | "optionalDependencies": { 1146 | "@cloudflare/workerd-darwin-64": "1.20231030.0", 1147 | "@cloudflare/workerd-darwin-arm64": "1.20231030.0", 1148 | "@cloudflare/workerd-linux-64": "1.20231030.0", 1149 | "@cloudflare/workerd-linux-arm64": "1.20231030.0", 1150 | "@cloudflare/workerd-windows-64": "1.20231030.0" 1151 | } 1152 | }, 1153 | "node_modules/wrangler": { 1154 | "version": "3.17.1", 1155 | "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.17.1.tgz", 1156 | "integrity": "sha512-Pr9+/tjFkthzG63uoVm1NtVvgokT6p92fy1UsOgrntHyTu0pZMC1VJzG0NC8Vhs+z/+yTT8AqVV6AiJb3w8ZOQ==", 1157 | "dev": true, 1158 | "dependencies": { 1159 | "@cloudflare/kv-asset-handler": "^0.2.0", 1160 | "@esbuild-plugins/node-globals-polyfill": "^0.2.3", 1161 | "@esbuild-plugins/node-modules-polyfill": "^0.2.2", 1162 | "blake3-wasm": "^2.1.5", 1163 | "chokidar": "^3.5.3", 1164 | "esbuild": "0.17.19", 1165 | "miniflare": "3.20231030.1", 1166 | "nanoid": "^3.3.3", 1167 | "path-to-regexp": "^6.2.0", 1168 | "resolve.exports": "^2.0.2", 1169 | "selfsigned": "^2.0.1", 1170 | "source-map": "0.6.1", 1171 | "source-map-support": "0.5.21", 1172 | "xxhash-wasm": "^1.0.1" 1173 | }, 1174 | "bin": { 1175 | "wrangler": "bin/wrangler.js", 1176 | "wrangler2": "bin/wrangler.js" 1177 | }, 1178 | "engines": { 1179 | "node": ">=16.17.0" 1180 | }, 1181 | "optionalDependencies": { 1182 | "fsevents": "~2.3.2" 1183 | } 1184 | }, 1185 | "node_modules/ws": { 1186 | "version": "8.14.2", 1187 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", 1188 | "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", 1189 | "dev": true, 1190 | "engines": { 1191 | "node": ">=10.0.0" 1192 | }, 1193 | "peerDependencies": { 1194 | "bufferutil": "^4.0.1", 1195 | "utf-8-validate": ">=5.0.2" 1196 | }, 1197 | "peerDependenciesMeta": { 1198 | "bufferutil": { 1199 | "optional": true 1200 | }, 1201 | "utf-8-validate": { 1202 | "optional": true 1203 | } 1204 | } 1205 | }, 1206 | "node_modules/xxhash-wasm": { 1207 | "version": "1.0.2", 1208 | "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz", 1209 | "integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==", 1210 | "dev": true 1211 | }, 1212 | "node_modules/youch": { 1213 | "version": "3.3.3", 1214 | "resolved": "https://registry.npmjs.org/youch/-/youch-3.3.3.tgz", 1215 | "integrity": "sha512-qSFXUk3UZBLfggAW3dJKg0BMblG5biqSF8M34E06o5CSsZtH92u9Hqmj2RzGiHDi64fhe83+4tENFP2DB6t6ZA==", 1216 | "dev": true, 1217 | "dependencies": { 1218 | "cookie": "^0.5.0", 1219 | "mustache": "^4.2.0", 1220 | "stacktracey": "^2.1.8" 1221 | } 1222 | }, 1223 | "node_modules/zod": { 1224 | "version": "3.22.4", 1225 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", 1226 | "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", 1227 | "dev": true, 1228 | "funding": { 1229 | "url": "https://github.com/sponsors/colinhacks" 1230 | } 1231 | } 1232 | } 1233 | } 1234 | --------------------------------------------------------------------------------