123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- from __future__ import annotations
- from typing import List, Dict, Any, Tuple, Optional
- from dataclasses import dataclass
- import logging
- import requests
- from piket_server import Person, db
- @dataclass(frozen=True)
- class SparseAardbeiPerson:
- full_name: str
- display_name: str
- aardbei_id: int
- is_leader: bool
- @classmethod
- def from_aardbei_dict(cls, data: Dict[str, Any]) -> SparseAardbeiPerson:
- return cls(
- full_name=data["member"]["person"]["full_name"],
- display_name=data["member"]["display_name"],
- aardbei_id=data["member"]["person"]["id"],
- is_leader=data["member"]["is_leader"],
- )
- @dataclass(frozen=True)
- class AardbeiMatch:
- local: Person
- remote: SparseAardbeiPerson
- @dataclass(frozen=True)
- class AardbeiLink:
- matches: List[AardbeiMatch]
- """People that exist on both sides, but aren't linked in the people table."""
- altered_name: List[AardbeiMatch]
- """People that are already linked but changed one of their names."""
- remote_only: List[SparseAardbeiPerson]
- """People that only exist on the remote."""
- def get_aardbei_people(token: str) -> List[SparseAardbeiPerson]:
- resp = requests.get(
- "https://aardbei.app/api/groups/0/", headers={"Authorization": f"Group {token}"}
- )
- resp.raise_for_status()
- members = resp.json()["group"]["members"]
- return [SparseAardbeiPerson.from_aardbei_dict(x) for x in members]
- def match_local_aardbei(aardbei_people: List[SparseAardbeiPerson]) -> AardbeiLink:
- matches: List[AardbeiMatch] = []
- altered_name: List[AardbeiMatch] = []
- remote_only: List[SparseAardbeiPerson] = []
- for aardbei_person in aardbei_people:
- p: Optional[Person] = Person.query.filter_by(
- aardbei_id=aardbei_person.aardbei_id
- ).one_or_none()
- if p is not None:
- if (
- p.full_name != aardbei_person.full_name
- or p.display_name != aardbei_person.display_name
- ):
- altered_name.append(AardbeiMatch(p, aardbei_person))
- else:
- logging.info(
- "OK: %s / %s (L%s/R%s)",
- p.full_name,
- p.display_name,
- p.person_id,
- p.aardbei_id,
- )
- continue
- p = Person.query.filter_by(full_name=aardbei_person.full_name).one_or_none()
- if p is not None:
- matches.append(AardbeiMatch(p, aardbei_person))
- else:
- remote_only.append(aardbei_person)
- return AardbeiLink(matches, altered_name, remote_only)
- def link_matches(matches: List[AardbeiMatch]) -> None:
- for match in matches:
- match.local.aardbei_id = match.remote.aardbei_id
- match.local.display_name = match.remote.display_name
- logging.info(
- "Linking local %s (%s) to remote %s (%s)",
- match.local.full_name,
- match.local.person_id,
- match.remote.display_name,
- match.remote.aardbei_id,
- )
- db.session.add(match.local)
- def create_missing(missing: List[SparseAardbeiPerson]) -> None:
- for person in missing:
- pnew = Person(
- full_name=person.full_name,
- display_name=person.display_name,
- aardbei_id=person.aardbei_id,
- active=False,
- )
- logging.info(
- "Creating new person for %s (%s)", person.full_name, person.aardbei_id
- )
- db.session.add(pnew)
- def update_names(matches: List[AardbeiMatch]) -> None:
- for match in matches:
- p = match.local
- aardbei_person = match.remote
- changed = False
- if p.full_name != aardbei_person.full_name:
- logging.info(
- "Updating %s (L%s/R%s) full name %s to %s",
- aardbei_person.full_name,
- p.person_id,
- aardbei_person.aardbei_id,
- p.full_name,
- aardbei_person.full_name,
- )
- p.full_name = aardbei_person.full_name
- changed = True
- if p.display_name != aardbei_person.display_name:
- logging.info(
- "Updating %s (L%s/R%s) display name %s to %s",
- aardbei_person.full_name,
- p.person_id,
- aardbei_person.aardbei_id,
- p.display_name,
- aardbei_person.display_name,
- )
- p.display_name = aardbei_person.display_name
- changed = True
- assert changed, "got match but didn't update anything"
- db.session.add(p)
- if __name__ == "__main__":
- logging.basicConfig(level=logging.INFO)
- token = input("Token: ")
- aardbei_people = get_aardbei_people(token)
- link = match_local_aardbei(aardbei_people)
- link_matches(link.matches)
- create_missing(link.remote_only)
- update_names(link.altered_name)
- confirm = input("Commit? Y/N")
- if confirm.lower() == "y":
- print("Committing.")
- db.session.commit()
- else:
- print("Not committing.")
|