newbies.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. from __future__ import annotations
  2. import datetime
  3. import itertools
  4. import sys
  5. import typing
  6. import urllib.parse
  7. import httpx
  8. import cache
  9. def main() -> None:
  10. since = sys.argv[1]
  11. c = httpx.Client()
  12. codes: dict[str, str] = {company['UserName'].casefold(): company['CompanyCode']
  13. for company in cache.get('https://rest.fnar.net/company/all', expiry=datetime.timedelta(hours=1))
  14. if company['UserName'] is not None}
  15. planets = ['Avalon', 'Berthier', 'Boucher', 'Nova Honshu', 'Promitor']
  16. joined: dict[str, int] = {}
  17. for planet in planets:
  18. print('querying', planet, 'chat...', file=sys.stderr)
  19. messages: typing.Sequence[Message] = c.get('https://api.fnar.net/chat/messages',
  20. params={'channel_names': planet + ' Global Site Owners'}).raise_for_status().json()
  21. for message in messages:
  22. if message['Type'] == 'JOINED':
  23. old_join = joined.get(message['SenderUserName'])
  24. if old_join is None or old_join > message['MessageTimestamp']:
  25. joined[message['SenderUserName']] = message['MessageTimestamp']
  26. threshold = int(datetime.datetime.strptime(since, '%Y-%m-%d').replace(tzinfo=datetime.UTC).timestamp() * 1000)
  27. for username, join_ts in list(joined.items()):
  28. if join_ts < threshold:
  29. del joined[username]
  30. relevant_cos = {co for username in joined.keys() if (co := codes.get(username))}
  31. for username in joined.keys():
  32. co = codes.get(username)
  33. if co is None:
  34. response = c.get('https://rest.fnar.net/user/' + urllib.parse.quote(username)).raise_for_status()
  35. if response.status_code != 204:
  36. co = response.json()['CompanyCode']
  37. if co is not None:
  38. relevant_cos.add(co)
  39. rep: dict[str, int] = {}
  40. for co_batch in itertools.batched(relevant_cos, 10):
  41. companies = c.get('https://api.fnar.net/company/lookup?' + '&'.join(f'company={co}' for co in co_batch)).raise_for_status().json()
  42. for company in companies:
  43. if company is not None:
  44. rep[company['UserName'].casefold()] = company['Reputation']
  45. for username, join_ts in sorted(joined.items(), key=lambda i: i[1]):
  46. join_str = datetime.datetime.fromtimestamp(join_ts/1000, tz=datetime.UTC).strftime('%Y-%m-%d %H:%M:%S')
  47. print(username, join_str, '', '', rep.get(username, ''), sep='\t')
  48. class Message(typing.TypedDict):
  49. Type: typing.Literal['JOINED', 'LEFT', 'MESSAGE']
  50. SenderUserName: str
  51. MessageTimestamp: int
  52. if __name__ == '__main__':
  53. main()