marvin_actions
Make actions for Marvin, one function for each action.
1#! /usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4""" 5Make actions for Marvin, one function for each action. 6""" 7from urllib.parse import quote_plus 8from urllib.request import urlopen 9import calendar 10import datetime 11import json 12import logging 13import random 14import requests 15 16from bs4 import BeautifulSoup 17 18LOG = logging.getLogger("action") 19 20def getAllActions(): 21 """ 22 Return all actions in an array. 23 """ 24 return [ 25 marvinExplainShell, 26 marvinGoogle, 27 marvinLunch, 28 marvinVideoOfToday, 29 marvinWhoIs, 30 marvinHelp, 31 marvinSource, 32 marvinBudord, 33 marvinQuote, 34 marvinWeather, 35 marvinSun, 36 marvinSayHi, 37 marvinSmile, 38 marvinStrip, 39 marvinTimeToBBQ, 40 marvinBirthday, 41 marvinNameday, 42 marvinUptime, 43 marvinStream, 44 marvinPrinciple, 45 marvinJoke, 46 marvinCommit 47 ] 48 49 50# Load all strings from file 51with open("marvin_strings.json", encoding="utf-8") as f: 52 STRINGS = json.load(f) 53 54 55def getString(key, key1=None): 56 """ 57 Get a string from the string database. 58 """ 59 data = STRINGS[key] 60 if isinstance(data, list): 61 res = data[random.randint(0, len(data) - 1)] 62 elif isinstance(data, dict): 63 if key1 is None: 64 res = data 65 else: 66 res = data[key1] 67 if isinstance(res, list): 68 res = res[random.randint(0, len(res) - 1)] 69 elif isinstance(data, str): 70 res = data 71 72 return res 73 74 75def marvinSmile(row): 76 """ 77 Make Marvin smile. 78 """ 79 msg = None 80 if any(r in row for r in ["smile", "le", "skratta", "smilies"]): 81 msg = getString("smile") 82 return msg 83 84 85def wordsAfterKeyWords(words, keyWords): 86 """ 87 Return all items in the words list after the first occurence 88 of an item in the keyWords list. 89 """ 90 kwIndex = [] 91 for kw in keyWords: 92 if kw in words: 93 kwIndex.append(words.index(kw)) 94 95 if not kwIndex: 96 return None 97 98 return words[min(kwIndex)+1:] 99 100 101def marvinGoogle(row): 102 """ 103 Let Marvin present an url to google. 104 """ 105 query = wordsAfterKeyWords(row, ["google", "googla"]) 106 if not query: 107 return None 108 109 searchStr = " ".join(query) 110 url = "https://www.google.se/search?q=" 111 url += quote_plus(searchStr) 112 msg = getString("google") 113 return msg.format(url) 114 115 116def marvinExplainShell(row): 117 """ 118 Let Marvin present an url to the service explain shell to 119 explain a shell command. 120 """ 121 query = wordsAfterKeyWords(row, ["explain", "förklara"]) 122 if not query: 123 return None 124 cmd = " ".join(query) 125 url = "https://explainshell.com/explain?cmd=" 126 url += quote_plus(cmd, "/:") 127 msg = getString("explainShell") 128 return msg.format(url) 129 130 131def marvinSource(row): 132 """ 133 State message about sourcecode. 134 """ 135 msg = None 136 if any(r in row for r in ["källkod", "source"]): 137 msg = getString("source") 138 139 return msg 140 141 142def marvinBudord(row): 143 """ 144 What are the budord for Marvin? 145 """ 146 msg = None 147 if any(r in row for r in ["budord", "stentavla"]): 148 if any(r in row for r in ["#1", "1"]): 149 msg = getString("budord", "#1") 150 elif any(r in row for r in ["#2", "2"]): 151 msg = getString("budord", "#2") 152 elif any(r in row for r in ["#3", "3"]): 153 msg = getString("budord", "#3") 154 elif any(r in row for r in ["#4", "4"]): 155 msg = getString("budord", "#4") 156 elif any(r in row for r in ["#5", "5"]): 157 msg = getString("budord", "#5") 158 159 return msg 160 161 162def marvinQuote(row): 163 """ 164 Make a quote. 165 """ 166 msg = None 167 if any(r in row for r in ["quote", "citat", "filosofi", "filosofera"]): 168 msg = getString("hitchhiker") 169 170 return msg 171 172 173def videoOfToday(): 174 """ 175 Check what day it is and provide a url to a suitable video together with a greeting. 176 """ 177 weekday = datetime.date.today().strftime("%A") 178 day = getString("video-of-today", weekday) 179 msg = day.get("message") 180 181 if day: 182 msg += " En passande video är " + day.get("url") 183 else: 184 msg += " Jag har ännu ingen passande video för denna dagen." 185 186 return msg 187 188 189def marvinVideoOfToday(row): 190 """ 191 Show the video of today. 192 """ 193 msg = None 194 if any(r in row for r in ["idag", "dagens"]): 195 if any(r in row for r in ["video", "youtube", "tube"]): 196 msg = videoOfToday() 197 198 return msg 199 200 201def marvinWhoIs(row): 202 """ 203 Who is Marvin. 204 """ 205 msg = None 206 if all(r in row for r in ["vem", "är"]): 207 msg = getString("whois") 208 209 return msg 210 211 212def marvinHelp(row): 213 """ 214 Provide a menu. 215 """ 216 msg = None 217 if any(r in row for r in ["hjälp", "help", "menu", "meny"]): 218 msg = getString("menu") 219 220 return msg 221 222 223def marvinSayHi(row): 224 """ 225 Say hi with a nice message. 226 """ 227 msg = None 228 if any(r in row for r in [ 229 "snälla", "hej", "tjena", "morsning", "morrn", "mår", "hallå", 230 "halloj", "läget", "snäll", "duktig", "träna", "träning", 231 "utbildning", "tack", "tacka", "tackar", "tacksam" 232 ]): 233 smile = getString("smile") 234 hello = getString("hello") 235 friendly = getString("friendly") 236 msg = f"{smile} {hello} {friendly}" 237 238 return msg 239 240 241def marvinLunch(row): 242 """ 243 Help decide where to eat. 244 """ 245 lunchOptions = { 246 'stan centrum karlskrona kna': 'karlskrona', 247 'ängelholm angelholm engelholm': 'angelholm', 248 'hässleholm hassleholm': 'hassleholm', 249 'malmö malmo malmoe': 'malmo', 250 'göteborg goteborg gbg': 'goteborg' 251 } 252 253 data = getString("lunch") 254 255 if any(r in row for r in ["lunch", "mat", "äta", "luncha"]): 256 places = data.get("location").get("bth") 257 for keys, value in lunchOptions.items(): 258 if any(r in row for r in keys.split(" ")): 259 places = data.get("location").get(value) 260 261 lunchStr = getString("lunch", "message") 262 return lunchStr.format(places[random.randint(0, len(places) - 1)]) 263 264 return None 265 266 267def marvinSun(row): 268 """ 269 Check when the sun goes up and down. 270 """ 271 msg = None 272 if any(r in row for r in ["sol", "solen", "solnedgång", "soluppgång", "sun"]): 273 try: 274 url = getString("sun", "url") 275 r = requests.get(url, timeout=5) 276 sundata = r.json() 277 # Formats the time from the response to HH:mm instead of hh:mm:ss 278 sunrise = sundata["results"]["sunrise"].split()[0][:-3] 279 sunset = sundata["results"]["sunset"].split()[0][:-3] 280 # The api uses AM/PM notation, this converts the sunset to 12 hour time 281 sunsetHour = int(sunset.split(":")[0]) + 12 282 sunset = str(sunsetHour) + sunset[-3:] 283 msg = getString("sun", "msg").format(sunrise, sunset) 284 return msg 285 286 except Exception as e: 287 LOG.error("Failed to get sun times: %s", e) 288 return getString("sun", "error") 289 290 return msg 291 292 293def marvinWeather(row): 294 """ 295 Check what the weather prognosis looks like. 296 """ 297 msg = "" 298 if any(r in row for r in ["väder", "vädret", "prognos", "prognosen", "smhi"]): 299 forecast = "" 300 observation = "" 301 302 try: 303 station_req = requests.get(getString("smhi", "station_url"), timeout=5) 304 weather_code:int = int(station_req.json().get("value")[0].get("value")) 305 306 weather_codes_req = requests.get(getString("smhi", "weather_codes_url"), timeout=5) 307 weather_codes_arr: list = weather_codes_req.json().get("entry") 308 309 current_weather_req = requests.get(getString("smhi", "current_weather_url"), timeout=5) 310 current_w_data: list = current_weather_req.json().get("timeSeries")[0].get("parameters") 311 312 for curr_w in current_w_data: 313 if curr_w.get("name") == "t": 314 forecast = curr_w.get("values")[0] 315 316 for code in weather_codes_arr: 317 if code.get("key") == weather_code: 318 observation = code.get("value") 319 320 msg = f"Karlskrona just nu: {forecast} °C. {observation}." 321 322 except Exception as e: 323 LOG.error("Failed to get weather: %s", e) 324 msg: str = getString("smhi", "failed") 325 326 return msg 327 328 329def marvinStrip(row): 330 """ 331 Get a comic strip. 332 """ 333 msg = None 334 if any(r in row for r in ["strip", "comic", "nöje", "paus"]): 335 msg = commitStrip(randomize=any(r in row for r in ["rand", "random", "slump", "lucky"])) 336 return msg 337 338 339def commitStrip(randomize=False): 340 """ 341 Latest or random comic strip from CommitStrip. 342 """ 343 msg = getString("commitstrip", "message") 344 345 if randomize: 346 first = getString("commitstrip", "first") 347 last = getString("commitstrip", "last") 348 rand = random.randint(first, last) 349 url = getString("commitstrip", "urlPage") + str(rand) 350 else: 351 url = getString("commitstrip", "url") 352 353 return msg.format(url=url) 354 355 356def marvinTimeToBBQ(row): 357 """ 358 Calcuate the time to next barbecue and print a appropriate msg 359 """ 360 msg = None 361 if any(r in row for r in ["grilla", "grill", "grillcon", "bbq"]): 362 url = getString("barbecue", "url") 363 nextDate = nextBBQ() 364 today = datetime.date.today() 365 daysRemaining = (nextDate - today).days 366 367 if daysRemaining == 0: 368 msg = getString("barbecue", "today") 369 elif daysRemaining == 1: 370 msg = getString("barbecue", "tomorrow") 371 elif 1 < daysRemaining < 14: 372 msg = getString("barbecue", "week") % nextDate 373 elif 14 < daysRemaining < 200: 374 msg = getString("barbecue", "base") % nextDate 375 else: 376 msg = getString("barbecue", "eternity") % nextDate 377 378 msg = url + ". " + msg 379 return msg 380 381def nextBBQ(): 382 """ 383 Calculate the next grillcon date after today 384 """ 385 386 MAY = 5 387 SEPTEMBER = 9 388 389 after = datetime.date.today() 390 spring = thirdFridayIn(after.year, MAY) 391 if after <= spring: 392 return spring 393 394 autumn = thirdFridayIn(after.year, SEPTEMBER) 395 if after <= autumn: 396 return autumn 397 398 return thirdFridayIn(after.year + 1, MAY) 399 400 401def thirdFridayIn(y, m): 402 """ 403 Get the third Friday in a given month and year 404 """ 405 THIRD = 2 406 FRIDAY = -1 407 408 # Start the weeks on saturday to prevent fridays from previous month 409 cal = calendar.Calendar(firstweekday=calendar.SATURDAY) 410 411 # Return the friday in the third week 412 return cal.monthdatescalendar(y, m)[THIRD][FRIDAY] 413 414 415def marvinBirthday(row): 416 """ 417 Check birthday info 418 """ 419 msg = None 420 if any(r in row for r in ["birthday", "födelsedag"]): 421 try: 422 url = getString("birthday", "url") 423 soup = BeautifulSoup(urlopen(url), "html.parser") 424 my_list = list() 425 426 for ana in soup.findAll('a'): 427 if ana.parent.name == 'strong': 428 my_list.append(ana.getText()) 429 430 my_list.pop() 431 my_strings = ', '.join(my_list) 432 if not my_strings: 433 msg = getString("birthday", "nobody") 434 else: 435 msg = getString("birthday", "somebody").format(my_strings) 436 437 except Exception as e: 438 LOG.error("Failed to get birthday: %s", e) 439 msg = getString("birthday", "error") 440 441 return msg 442 443def marvinNameday(row): 444 """ 445 Check current nameday 446 """ 447 msg = None 448 if any(r in row for r in ["nameday", "namnsdag"]): 449 try: 450 now = datetime.datetime.now() 451 raw_url = "https://api.dryg.net/dagar/v2.1/{year}/{month}/{day}" 452 url = raw_url.format(year=now.year, month=now.month, day=now.day) 453 r = requests.get(url, timeout=5) 454 nameday_data = r.json() 455 names = nameday_data["dagar"][0]["namnsdag"] 456 parsed_names = formatNames(names) 457 if names: 458 msg = getString("nameday", "somebody").format(parsed_names) 459 else: 460 msg = getString("nameday", "nobody") 461 except Exception as e: 462 LOG.error("Failed to get nameday: %s", e) 463 msg = getString("nameday", "error") 464 return msg 465 466def formatNames(names): 467 """ 468 Parses namedata from nameday API 469 """ 470 if len(names) > 1: 471 return " och ".join([", ".join(names[:-1])] + names[-1:]) 472 return "".join(names) 473 474def marvinUptime(row): 475 """ 476 Display info about uptime tournament 477 """ 478 msg = None 479 if "uptime" in row: 480 msg = getString("uptime", "info") 481 return msg 482 483def marvinStream(row): 484 """ 485 Display info about stream 486 """ 487 msg = None 488 if any(r in row for r in ["stream", "streama", "ström", "strömma"]): 489 msg = getString("stream", "info") 490 return msg 491 492def marvinPrinciple(row): 493 """ 494 Display one selected software principle, or provide one as random 495 """ 496 msg = None 497 if any(r in row for r in ["principle", "princip", "principer"]): 498 principles = getString("principle") 499 principleKeys = list(principles.keys()) 500 matchedKeys = [k for k in row if k in principleKeys] 501 if matchedKeys: 502 msg = principles[matchedKeys.pop()] 503 else: 504 msg = principles[random.choice(principleKeys)] 505 return msg 506 507def getJoke(): 508 """ 509 Retrieves joke from api.chucknorris.io/jokes/random?category=dev 510 """ 511 try: 512 url = getString("joke", "url") 513 r = requests.get(url, timeout=5) 514 joke_data = r.json() 515 return joke_data["value"] 516 except Exception as e: 517 LOG.error("Failed to get joke: %s", e) 518 return getString("joke", "error") 519 520def marvinJoke(row): 521 """ 522 Display a random Chuck Norris joke 523 """ 524 msg = None 525 if any(r in row for r in ["joke", "skämt", "chuck norris", "chuck", "norris"]): 526 msg = getJoke() 527 return msg 528 529def getCommit(): 530 """ 531 Retrieves random commit message from whatthecommit.com/index.html 532 """ 533 try: 534 url = getString("commit", "url") 535 r = requests.get(url, timeout=5) 536 res = r.text.strip() 537 msg = f"Använd detta meddelandet: '{res}'" 538 return msg 539 except Exception as e: 540 LOG.error("Failed to get commit message: %s", e) 541 return getString("commit", "error") 542 543def marvinCommit(row): 544 """ 545 Display a random commit message 546 """ 547 msg = None 548 if any(r in row for r in ["commit", "-m"]): 549 msg = getCommit() 550 return msg
21def getAllActions(): 22 """ 23 Return all actions in an array. 24 """ 25 return [ 26 marvinExplainShell, 27 marvinGoogle, 28 marvinLunch, 29 marvinVideoOfToday, 30 marvinWhoIs, 31 marvinHelp, 32 marvinSource, 33 marvinBudord, 34 marvinQuote, 35 marvinWeather, 36 marvinSun, 37 marvinSayHi, 38 marvinSmile, 39 marvinStrip, 40 marvinTimeToBBQ, 41 marvinBirthday, 42 marvinNameday, 43 marvinUptime, 44 marvinStream, 45 marvinPrinciple, 46 marvinJoke, 47 marvinCommit 48 ]
Return all actions in an array.
56def getString(key, key1=None): 57 """ 58 Get a string from the string database. 59 """ 60 data = STRINGS[key] 61 if isinstance(data, list): 62 res = data[random.randint(0, len(data) - 1)] 63 elif isinstance(data, dict): 64 if key1 is None: 65 res = data 66 else: 67 res = data[key1] 68 if isinstance(res, list): 69 res = res[random.randint(0, len(res) - 1)] 70 elif isinstance(data, str): 71 res = data 72 73 return res
Get a string from the string database.
76def marvinSmile(row): 77 """ 78 Make Marvin smile. 79 """ 80 msg = None 81 if any(r in row for r in ["smile", "le", "skratta", "smilies"]): 82 msg = getString("smile") 83 return msg
Make Marvin smile.
86def wordsAfterKeyWords(words, keyWords): 87 """ 88 Return all items in the words list after the first occurence 89 of an item in the keyWords list. 90 """ 91 kwIndex = [] 92 for kw in keyWords: 93 if kw in words: 94 kwIndex.append(words.index(kw)) 95 96 if not kwIndex: 97 return None 98 99 return words[min(kwIndex)+1:]
Return all items in the words list after the first occurence of an item in the keyWords list.
102def marvinGoogle(row): 103 """ 104 Let Marvin present an url to google. 105 """ 106 query = wordsAfterKeyWords(row, ["google", "googla"]) 107 if not query: 108 return None 109 110 searchStr = " ".join(query) 111 url = "https://www.google.se/search?q=" 112 url += quote_plus(searchStr) 113 msg = getString("google") 114 return msg.format(url)
Let Marvin present an url to google.
117def marvinExplainShell(row): 118 """ 119 Let Marvin present an url to the service explain shell to 120 explain a shell command. 121 """ 122 query = wordsAfterKeyWords(row, ["explain", "förklara"]) 123 if not query: 124 return None 125 cmd = " ".join(query) 126 url = "https://explainshell.com/explain?cmd=" 127 url += quote_plus(cmd, "/:") 128 msg = getString("explainShell") 129 return msg.format(url)
Let Marvin present an url to the service explain shell to explain a shell command.
132def marvinSource(row): 133 """ 134 State message about sourcecode. 135 """ 136 msg = None 137 if any(r in row for r in ["källkod", "source"]): 138 msg = getString("source") 139 140 return msg
State message about sourcecode.
143def marvinBudord(row): 144 """ 145 What are the budord for Marvin? 146 """ 147 msg = None 148 if any(r in row for r in ["budord", "stentavla"]): 149 if any(r in row for r in ["#1", "1"]): 150 msg = getString("budord", "#1") 151 elif any(r in row for r in ["#2", "2"]): 152 msg = getString("budord", "#2") 153 elif any(r in row for r in ["#3", "3"]): 154 msg = getString("budord", "#3") 155 elif any(r in row for r in ["#4", "4"]): 156 msg = getString("budord", "#4") 157 elif any(r in row for r in ["#5", "5"]): 158 msg = getString("budord", "#5") 159 160 return msg
What are the budord for Marvin?
163def marvinQuote(row): 164 """ 165 Make a quote. 166 """ 167 msg = None 168 if any(r in row for r in ["quote", "citat", "filosofi", "filosofera"]): 169 msg = getString("hitchhiker") 170 171 return msg
Make a quote.
174def videoOfToday(): 175 """ 176 Check what day it is and provide a url to a suitable video together with a greeting. 177 """ 178 weekday = datetime.date.today().strftime("%A") 179 day = getString("video-of-today", weekday) 180 msg = day.get("message") 181 182 if day: 183 msg += " En passande video är " + day.get("url") 184 else: 185 msg += " Jag har ännu ingen passande video för denna dagen." 186 187 return msg
Check what day it is and provide a url to a suitable video together with a greeting.
190def marvinVideoOfToday(row): 191 """ 192 Show the video of today. 193 """ 194 msg = None 195 if any(r in row for r in ["idag", "dagens"]): 196 if any(r in row for r in ["video", "youtube", "tube"]): 197 msg = videoOfToday() 198 199 return msg
Show the video of today.
202def marvinWhoIs(row): 203 """ 204 Who is Marvin. 205 """ 206 msg = None 207 if all(r in row for r in ["vem", "är"]): 208 msg = getString("whois") 209 210 return msg
Who is Marvin.
213def marvinHelp(row): 214 """ 215 Provide a menu. 216 """ 217 msg = None 218 if any(r in row for r in ["hjälp", "help", "menu", "meny"]): 219 msg = getString("menu") 220 221 return msg
Provide a menu.
224def marvinSayHi(row): 225 """ 226 Say hi with a nice message. 227 """ 228 msg = None 229 if any(r in row for r in [ 230 "snälla", "hej", "tjena", "morsning", "morrn", "mår", "hallå", 231 "halloj", "läget", "snäll", "duktig", "träna", "träning", 232 "utbildning", "tack", "tacka", "tackar", "tacksam" 233 ]): 234 smile = getString("smile") 235 hello = getString("hello") 236 friendly = getString("friendly") 237 msg = f"{smile} {hello} {friendly}" 238 239 return msg
Say hi with a nice message.
242def marvinLunch(row): 243 """ 244 Help decide where to eat. 245 """ 246 lunchOptions = { 247 'stan centrum karlskrona kna': 'karlskrona', 248 'ängelholm angelholm engelholm': 'angelholm', 249 'hässleholm hassleholm': 'hassleholm', 250 'malmö malmo malmoe': 'malmo', 251 'göteborg goteborg gbg': 'goteborg' 252 } 253 254 data = getString("lunch") 255 256 if any(r in row for r in ["lunch", "mat", "äta", "luncha"]): 257 places = data.get("location").get("bth") 258 for keys, value in lunchOptions.items(): 259 if any(r in row for r in keys.split(" ")): 260 places = data.get("location").get(value) 261 262 lunchStr = getString("lunch", "message") 263 return lunchStr.format(places[random.randint(0, len(places) - 1)]) 264 265 return None
Help decide where to eat.
268def marvinSun(row): 269 """ 270 Check when the sun goes up and down. 271 """ 272 msg = None 273 if any(r in row for r in ["sol", "solen", "solnedgång", "soluppgång", "sun"]): 274 try: 275 url = getString("sun", "url") 276 r = requests.get(url, timeout=5) 277 sundata = r.json() 278 # Formats the time from the response to HH:mm instead of hh:mm:ss 279 sunrise = sundata["results"]["sunrise"].split()[0][:-3] 280 sunset = sundata["results"]["sunset"].split()[0][:-3] 281 # The api uses AM/PM notation, this converts the sunset to 12 hour time 282 sunsetHour = int(sunset.split(":")[0]) + 12 283 sunset = str(sunsetHour) + sunset[-3:] 284 msg = getString("sun", "msg").format(sunrise, sunset) 285 return msg 286 287 except Exception as e: 288 LOG.error("Failed to get sun times: %s", e) 289 return getString("sun", "error") 290 291 return msg
Check when the sun goes up and down.
294def marvinWeather(row): 295 """ 296 Check what the weather prognosis looks like. 297 """ 298 msg = "" 299 if any(r in row for r in ["väder", "vädret", "prognos", "prognosen", "smhi"]): 300 forecast = "" 301 observation = "" 302 303 try: 304 station_req = requests.get(getString("smhi", "station_url"), timeout=5) 305 weather_code:int = int(station_req.json().get("value")[0].get("value")) 306 307 weather_codes_req = requests.get(getString("smhi", "weather_codes_url"), timeout=5) 308 weather_codes_arr: list = weather_codes_req.json().get("entry") 309 310 current_weather_req = requests.get(getString("smhi", "current_weather_url"), timeout=5) 311 current_w_data: list = current_weather_req.json().get("timeSeries")[0].get("parameters") 312 313 for curr_w in current_w_data: 314 if curr_w.get("name") == "t": 315 forecast = curr_w.get("values")[0] 316 317 for code in weather_codes_arr: 318 if code.get("key") == weather_code: 319 observation = code.get("value") 320 321 msg = f"Karlskrona just nu: {forecast} °C. {observation}." 322 323 except Exception as e: 324 LOG.error("Failed to get weather: %s", e) 325 msg: str = getString("smhi", "failed") 326 327 return msg
Check what the weather prognosis looks like.
330def marvinStrip(row): 331 """ 332 Get a comic strip. 333 """ 334 msg = None 335 if any(r in row for r in ["strip", "comic", "nöje", "paus"]): 336 msg = commitStrip(randomize=any(r in row for r in ["rand", "random", "slump", "lucky"])) 337 return msg
Get a comic strip.
340def commitStrip(randomize=False): 341 """ 342 Latest or random comic strip from CommitStrip. 343 """ 344 msg = getString("commitstrip", "message") 345 346 if randomize: 347 first = getString("commitstrip", "first") 348 last = getString("commitstrip", "last") 349 rand = random.randint(first, last) 350 url = getString("commitstrip", "urlPage") + str(rand) 351 else: 352 url = getString("commitstrip", "url") 353 354 return msg.format(url=url)
Latest or random comic strip from CommitStrip.
357def marvinTimeToBBQ(row): 358 """ 359 Calcuate the time to next barbecue and print a appropriate msg 360 """ 361 msg = None 362 if any(r in row for r in ["grilla", "grill", "grillcon", "bbq"]): 363 url = getString("barbecue", "url") 364 nextDate = nextBBQ() 365 today = datetime.date.today() 366 daysRemaining = (nextDate - today).days 367 368 if daysRemaining == 0: 369 msg = getString("barbecue", "today") 370 elif daysRemaining == 1: 371 msg = getString("barbecue", "tomorrow") 372 elif 1 < daysRemaining < 14: 373 msg = getString("barbecue", "week") % nextDate 374 elif 14 < daysRemaining < 200: 375 msg = getString("barbecue", "base") % nextDate 376 else: 377 msg = getString("barbecue", "eternity") % nextDate 378 379 msg = url + ". " + msg 380 return msg
Calcuate the time to next barbecue and print a appropriate msg
382def nextBBQ(): 383 """ 384 Calculate the next grillcon date after today 385 """ 386 387 MAY = 5 388 SEPTEMBER = 9 389 390 after = datetime.date.today() 391 spring = thirdFridayIn(after.year, MAY) 392 if after <= spring: 393 return spring 394 395 autumn = thirdFridayIn(after.year, SEPTEMBER) 396 if after <= autumn: 397 return autumn 398 399 return thirdFridayIn(after.year + 1, MAY)
Calculate the next grillcon date after today
402def thirdFridayIn(y, m): 403 """ 404 Get the third Friday in a given month and year 405 """ 406 THIRD = 2 407 FRIDAY = -1 408 409 # Start the weeks on saturday to prevent fridays from previous month 410 cal = calendar.Calendar(firstweekday=calendar.SATURDAY) 411 412 # Return the friday in the third week 413 return cal.monthdatescalendar(y, m)[THIRD][FRIDAY]
Get the third Friday in a given month and year
416def marvinBirthday(row): 417 """ 418 Check birthday info 419 """ 420 msg = None 421 if any(r in row for r in ["birthday", "födelsedag"]): 422 try: 423 url = getString("birthday", "url") 424 soup = BeautifulSoup(urlopen(url), "html.parser") 425 my_list = list() 426 427 for ana in soup.findAll('a'): 428 if ana.parent.name == 'strong': 429 my_list.append(ana.getText()) 430 431 my_list.pop() 432 my_strings = ', '.join(my_list) 433 if not my_strings: 434 msg = getString("birthday", "nobody") 435 else: 436 msg = getString("birthday", "somebody").format(my_strings) 437 438 except Exception as e: 439 LOG.error("Failed to get birthday: %s", e) 440 msg = getString("birthday", "error") 441 442 return msg
Check birthday info
444def marvinNameday(row): 445 """ 446 Check current nameday 447 """ 448 msg = None 449 if any(r in row for r in ["nameday", "namnsdag"]): 450 try: 451 now = datetime.datetime.now() 452 raw_url = "https://api.dryg.net/dagar/v2.1/{year}/{month}/{day}" 453 url = raw_url.format(year=now.year, month=now.month, day=now.day) 454 r = requests.get(url, timeout=5) 455 nameday_data = r.json() 456 names = nameday_data["dagar"][0]["namnsdag"] 457 parsed_names = formatNames(names) 458 if names: 459 msg = getString("nameday", "somebody").format(parsed_names) 460 else: 461 msg = getString("nameday", "nobody") 462 except Exception as e: 463 LOG.error("Failed to get nameday: %s", e) 464 msg = getString("nameday", "error") 465 return msg
Check current nameday
467def formatNames(names): 468 """ 469 Parses namedata from nameday API 470 """ 471 if len(names) > 1: 472 return " och ".join([", ".join(names[:-1])] + names[-1:]) 473 return "".join(names)
Parses namedata from nameday API
475def marvinUptime(row): 476 """ 477 Display info about uptime tournament 478 """ 479 msg = None 480 if "uptime" in row: 481 msg = getString("uptime", "info") 482 return msg
Display info about uptime tournament
484def marvinStream(row): 485 """ 486 Display info about stream 487 """ 488 msg = None 489 if any(r in row for r in ["stream", "streama", "ström", "strömma"]): 490 msg = getString("stream", "info") 491 return msg
Display info about stream
493def marvinPrinciple(row): 494 """ 495 Display one selected software principle, or provide one as random 496 """ 497 msg = None 498 if any(r in row for r in ["principle", "princip", "principer"]): 499 principles = getString("principle") 500 principleKeys = list(principles.keys()) 501 matchedKeys = [k for k in row if k in principleKeys] 502 if matchedKeys: 503 msg = principles[matchedKeys.pop()] 504 else: 505 msg = principles[random.choice(principleKeys)] 506 return msg
Display one selected software principle, or provide one as random
508def getJoke(): 509 """ 510 Retrieves joke from api.chucknorris.io/jokes/random?category=dev 511 """ 512 try: 513 url = getString("joke", "url") 514 r = requests.get(url, timeout=5) 515 joke_data = r.json() 516 return joke_data["value"] 517 except Exception as e: 518 LOG.error("Failed to get joke: %s", e) 519 return getString("joke", "error")
Retrieves joke from api.chucknorris.io/jokes/random?category=dev
521def marvinJoke(row): 522 """ 523 Display a random Chuck Norris joke 524 """ 525 msg = None 526 if any(r in row for r in ["joke", "skämt", "chuck norris", "chuck", "norris"]): 527 msg = getJoke() 528 return msg
Display a random Chuck Norris joke
530def getCommit(): 531 """ 532 Retrieves random commit message from whatthecommit.com/index.html 533 """ 534 try: 535 url = getString("commit", "url") 536 r = requests.get(url, timeout=5) 537 res = r.text.strip() 538 msg = f"Använd detta meddelandet: '{res}'" 539 return msg 540 except Exception as e: 541 LOG.error("Failed to get commit message: %s", e) 542 return getString("commit", "error")
Retrieves random commit message from whatthecommit.com/index.html
544def marvinCommit(row): 545 """ 546 Display a random commit message 547 """ 548 msg = None 549 if any(r in row for r in ["commit", "-m"]): 550 msg = getCommit() 551 return msg
Display a random commit message