├── lastUpdate.txt ├── img ├── ogp.png ├── graph.png └── icon.png ├── style.css ├── README.md ├── .github └── workflows │ └── update.yml ├── update.py └── index.html /lastUpdate.txt: -------------------------------------------------------------------------------- 1 | 2023/5/8 16:45 -------------------------------------------------------------------------------- /img/ogp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morioprog/covid19-rating-graph/HEAD/img/ogp.png -------------------------------------------------------------------------------- /img/graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morioprog/covid19-rating-graph/HEAD/img/graph.png -------------------------------------------------------------------------------- /img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morioprog/covid19-rating-graph/HEAD/img/icon.png -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | body { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | } 6 | 7 | ul { 8 | list-style: disc; 9 | } 10 | 11 | .ul-center { 12 | display: flex; 13 | align-items: center; 14 | flex-direction: column; 15 | } 16 | 17 | .center { 18 | text-align: center; 19 | } 20 | 21 | .emphasize { 22 | color: red; 23 | font-weight: bold; 24 | } 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

3 | 4 | COVID19 Rating Graph 5 | 6 |

7 | 8 | [![Try!](https://img.shields.io/badge/Try!-GitHub%20Pages-blue?logo=github)](https://morioprog.github.io/covid19-rating-graph/) 9 | [![Follow @covid19_rating](https://img.shields.io/badge/Follow-@covid19__rating-00aced?logo=twitter)](https://twitter.com/covid19_rating) 10 | [![Update HTML](https://github.com/morioprog/covid19-rating-graph/actions/workflows/update.yml/badge.svg?branch=main)](https://github.com/morioprog/covid19-rating-graph/actions/workflows/update.yml) 11 | 12 | [![最新のグラフ](img/ogp.png)](https://morioprog.github.io/covid19-rating-graph/) 13 |
14 | -------------------------------------------------------------------------------- /.github/workflows/update.yml: -------------------------------------------------------------------------------- 1 | name: "Update HTML" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | schedule: 8 | - cron: "*/20 * * * *" 9 | 10 | jobs: 11 | update: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Setup Python 16 | uses: actions/setup-python@v2 17 | with: 18 | python-version: "3.x" 19 | - name: Install dependencies 20 | run: | 21 | python -m pip install --upgrade pip 22 | pip install requests selenium Pillow tweepy 23 | - name: Install Japanese font 24 | run: sudo apt-get install fonts-ipafont 25 | - name: Prepare Selenium 26 | uses: nanasess/setup-chromedriver@v1.0.5 27 | - name: Start XVFB 28 | run: Xvfb :99 & 29 | - name: Update 30 | run: | 31 | mkdir -p img 32 | if python update.py; then 33 | git config user.name github-actions 34 | git config user.email github-actions@github.com 35 | git add index.html img/ogp.png img/graph.png lastUpdate.txt 36 | git commit -m "Update index.html and images" 37 | git push 38 | fi 39 | env: 40 | DISPLAY: :99 41 | TWITTER_API_KEY: ${{ secrets.TWITTER_API_KEY }} 42 | TWITTER_API_SECRET_KEY: ${{ secrets.TWITTER_API_SECRET_KEY }} 43 | TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} 44 | TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} 45 | -------------------------------------------------------------------------------- /update.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import time 4 | import tweepy 5 | import datetime 6 | import requests 7 | from PIL import Image 8 | from selenium import webdriver 9 | 10 | 11 | def fetch_api(): 12 | api = 'https://raw.githubusercontent.com/tokyo-metropolitan-gov/covid19/master/data/daily_positive_detail.json' 13 | req = requests.get(api) 14 | json = req.json() 15 | last_update = json['date'] 16 | data = json['data'] 17 | return last_update, data 18 | 19 | 20 | def update_lastupdate(last_update, file='lastUpdate.txt'): 21 | with open(file, mode='r') as f: 22 | if f.read() == last_update: 23 | return False 24 | with open(file, mode='w') as f: 25 | f.write(last_update) 26 | return True 27 | 28 | 29 | def rate_to_color(rate): 30 | if rate >= 2800: 31 | return '#FF0000' 32 | if rate >= 2400: 33 | return '#FF8000' 34 | if rate >= 2000: 35 | return '#C0C000' 36 | if rate >= 1600: 37 | return '#0000FF' 38 | if rate >= 1200: 39 | return '#00C0C0' 40 | if rate >= 800: 41 | return '#008000' 42 | if rate >= 400: 43 | return '#804000' 44 | if rate > 0: 45 | return '#808080' 46 | return '#000000' 47 | 48 | 49 | def rating_diff(old_rating, new_rating): 50 | return f"{'+' if old_rating < new_rating else ''}{new_rating - old_rating}" 51 | 52 | 53 | def convert_dict(dct): 54 | ret = [] 55 | old_rating = 0 56 | for e in dct: 57 | ret.append({ 58 | "ContestName": "東京都新規陽性者数の遷移", 59 | "OldRating": old_rating, 60 | "NewRating": e['count'], 61 | "EndTime": datetime.datetime.strptime(f"{e['diagnosed_date']}+0000", '%Y-%m-%d%z').timestamp(), 62 | "Place": -1, 63 | "StandingsUrl": "#", 64 | }) 65 | old_rating = e['count'] 66 | return ret 67 | 68 | 69 | def generate_ogp_html(dct, old_r, new_r, dt): 70 | with open('ogp.html', mode='w') as f: 71 | f.write(f'''\ 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
81 |
82 |
83 |
84 |
85 |
86 |
{last_update[5:-6]} ({"月火水木金土日"[dt.weekday()]})
87 |
{old_r}
88 |
89 |
{new_r}
90 |
({rating_diff(old_r, new_r)})
91 |
92 |
93 | 94 | 95 | 96 | 99 | 100 | 101 | ''') 102 | 103 | 104 | def save_ogp_image(): 105 | driver = webdriver.Chrome() 106 | driver.get( 107 | 'file:///home/runner/work/covid19-rating-graph/covid19-rating-graph/ogp.html') 108 | time.sleep(20) # ??? 109 | driver.save_screenshot("img/ogp_bef.png") 110 | driver.quit() 111 | 112 | im = Image.open('img/ogp_bef.png') 113 | im.crop((0, 0, 838, 440)).save('img/ogp.png', quality=95) 114 | 115 | im = Image.open('img/ogp_bef.png') 116 | im.crop((0, 0, 640, 440)).save('img/graph.png', quality=95) 117 | 118 | 119 | def tweet_graph(tweet, img): 120 | AT = os.environ['TWITTER_ACCESS_TOKEN'] 121 | AS = os.environ['TWITTER_ACCESS_TOKEN_SECRET'] 122 | CK = os.environ['TWITTER_API_KEY'] 123 | CS = os.environ['TWITTER_API_SECRET_KEY'] 124 | auth = tweepy.OAuthHandler(CK, CS) 125 | auth.set_access_token(AT, AS) 126 | api = tweepy.API(auth) 127 | media_ids = [api.media_upload(img).media_id] 128 | api.update_status(status=tweet, media_ids=media_ids) 129 | 130 | 131 | def generate_index_html(dct, tweet): 132 | with open('index.html', mode='w') as f: 133 | f.write(f'''\ 134 | 135 | 136 | COVID-19 Rating Graph 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 |
153 |
154 |

COVID-19 Rating Graph

155 |

完全に非公式です。

156 |
157 |

158 | 〜 159 | 160 | 161 |

162 |
163 |
164 | 170 |
171 | 177 | 183 |
184 |
185 |
186 | 187 | 188 | 189 | 190 | 216 | 217 | 218 | ''') 219 | 220 | 221 | if __name__ == '__main__': 222 | last_update, data = fetch_api() 223 | # No update 224 | if not update_lastupdate(last_update): 225 | sys.exit(1) 226 | old_r = data[-2]['count'] 227 | new_r = data[-1]['count'] 228 | dct = convert_dict(data) 229 | y, m, d = map(int, last_update[:-6].split('/')) 230 | last_update_dt = datetime.datetime(year=y, month=m, day=d) 231 | generate_ogp_html(dct, old_r, new_r, last_update_dt) 232 | save_ogp_image() 233 | tweet = f'''\ 234 | 東京都新規陽性者数({last_update[:-6]}更新) 235 | レーティング:{old_r}→{new_r} ({rating_diff(old_r, new_r)}) {':|' if old_r == new_r else ':(' if old_r < new_r else ':)'} 236 | {'Highestを更新してしまいました...' if max(e['count'] for e in data[:-1]) < data[-1]['count'] else ''} 237 | #COVID19RatingGraph 238 | ''' 239 | tweet_graph( 240 | tweet + 'https://morioprog.github.io/covid19-rating-graph/', 'img/ogp.png') 241 | generate_index_html(dct, tweet) 242 | sys.exit(0) 243 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | COVID-19 Rating Graph 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 |

COVID-19 Rating Graph

22 |

完全に非公式です。

23 |
24 |

25 | 〜 26 | 27 | 28 |

29 |
30 |
31 | 37 |
38 | 48 | 54 |
55 |
56 |
57 | 58 | 59 | 60 | 61 | 87 | 88 | 89 | --------------------------------------------------------------------------------