import re from typing import NamedTuple import feedparser from erepublik.constants import COUNTRIES region = "[\w\(\)\- ']+" country = "(Resistance force of )?[\w\(\)\- ]+" citizen = "[\w\(\)\-\. \d]+" class EventKind(NamedTuple): name: str regex: re.Pattern format: str events = [ EventKind( "Region attacked", re.compile(rf"(?P{country}) attacked (?P{region}), (?P{country})"), "{invader} attacked {defender} ({region})", ), EventKind( "Region secured", re.compile(rf"(?P{region}) was secured by (?P{country}) in the war versus ?(?P{country})?"), "{defender} defended {invader}'s attack ({region})", ), EventKind( "Region conquered", re.compile(rf"(?P{region}) was conquered by (?P{country}) in the war versus ?(?P{country})?"), "{invader} conquered {region} from {defender}", ), EventKind( "War approved", re.compile(rf"(?P{country}) declared war on (?P{country})"), "{invader} declared war against {defender}", ), EventKind( "War declared", re.compile(rf"President of (?P{country}) proposed a war declaration against (?P{country})"), "{invader} proposed a war declaration on {defender}", ), EventKind( "War rejected", re.compile(rf"The proposal for declaring war against (?P{country}) was rejected."), "{current_country} rejected war declaration on {defender}", ), EventKind( "MPP proposed", re.compile(rf"President of (?P{country}) proposed an alliance with (?P{country})"), "{country} proposed MPP with {partner}", ), EventKind( "MPP approved", re.compile(rf"(?P{country}) signed an alliance with (?P{country})"), "{country} signed a MPP with {partner}", ), EventKind( "MPP rejected", re.compile(rf"The alliance between (?P{country}) and (?P{country}) was rejected"), "MPP between {country} and {partner} was rejected", ), EventKind( "Airstrike proposed", re.compile(rf"President of (?P{country}) proposed an airstrike against (?P{country})"), "{invader} proposed an airstrike against {defender}", ), EventKind( "Airstrike approved", re.compile(rf"(?P{country}) prepares an airstrike on (?P{country})"), "{invader} approved an airstrike against {defender}", ), EventKind( "Airstrike rejected", re.compile(rf"The airstrike on (?P{country}) was rejected"), "{current_country} rejected the airstrike against {defender}", ), EventKind( "NE proposed", re.compile(rf"(?P{country}) has declared (?P{country}) as a Natural Enemy"), "{invader} proposed Natural Enemy declaration against {defender}", ), EventKind( "NE approved", re.compile(rf"(?P{country}) has been proposed as Natural Enemy"), "{current_country} declared {defender} as Natural Enemy", ), EventKind( "NE rejected", re.compile(rf"(?P{country}) as new Natural Enemy proposal has been rejected"), "{current_country} rejected {defender} as Natural Enemy", ), EventKind( "NE stopped", re.compile(rf"(?P{country}) is no longer a Natural Enemy for (?P{country})"), "{invader} removed Natural Enemy from {defender}", ), EventKind( "NE cleared", re.compile(rf"(?P{country}) no longer has a Natural Enemy"), "{country} no longer has a Natural Enemy" ), EventKind("NE reset", re.compile("No Natural Enemy law has been proposed."), "{current_country} has proposed to clear Natural Enemy"), EventKind( "Peace proposal", re.compile(rf"President of (?P{country}) proposed a peace in the war against (?P{country})"), "{defender} proposed peace against {invader}", ), EventKind( "Peace proposal", re.compile(rf"(?P{country}) proposed peace in the war against (?P{country})"), "{defender} proposed peace against {invader}", ), EventKind( "Peace approved", re.compile(rf"(?P{country}) signed a peace treaty with (?P{country})"), "{invader} and {defender} is not in peace", ), EventKind( "Peace rejected", re.compile(rf"The proposed peace treaty between (?P{country}) and (?P{country}) was rejected"), "{defender} and {invader} did not sign a peace treaty", ), EventKind( "Embargo proposed", re.compile(rf"President of (?P{country}) proposed to stop the trade with (?P{country})"), "{major} proposed trade embargo against {minor}", ), EventKind( "Embargo approved", re.compile(rf"(?P{country}) stopped trading with (?P{country})"), "{major} declared trade ambargo against {minor}", ), EventKind( "Donation proposed", re.compile(rf"A congress donation to (?P{citizen}) was proposed"), "{current_country} proposed a donation to {org}", ), EventKind( "Donation approved", re.compile(rf"(?P{country}) made a donation to (?P{citizen})"), "{current_country} approved a donation to {org}", ), EventKind( "Donation rejected", re.compile(rf"The proposal for a congress donation to (?P{citizen}) was rejected"), "{current_country} rejected a donation to {org}", ), EventKind( "RW started", re.compile(rf"A resistance has started in (?P{region})"), "Resistance war was opened in {region} ({current_country})", ), EventKind( "Res Concession", re.compile( rf'A Resource Concession law to //www.erepublik.com(?P{country}) has been proposed' ), "{source} proposed resource concession to {target}", ), EventKind( "Res Concession", re.compile( rf'A Resource Concession law to //www.erepublik.com(?P{country}) has been approved' ), "{source} approved resource concession to {target}", ), EventKind( "CP impeachment", re.compile(rf"A president impeachment against (?P{citizen}) was proposed"), "Impeachment against {cp} president of {current_country} was proposed", ), EventKind( "CP impeachment", re.compile("The president impeachment proposal has been rejected"), "Impeachment against president of {current_country} was rejected", ), EventKind("Minimum Wage", re.compile("A new minimum wage was proposed"), "A new minimum wage in {current_country} was proposed"), EventKind( "Minimum Wage", re.compile("The proposal for a minimum wage change was rejected"), "The new minimum wage proposal in {current_country} was rejected", ), EventKind("WorkTax", re.compile(rf"(?P{country}) now has a new Work Tax"), "{country} has new Work Tax"), EventKind("Product Tax", re.compile(rf"Taxes for (?P[\w ]+) changed"), "{current_country} changed taxes for {product}"), EventKind( "Product Tax", re.compile(rf"Tax proposal of tax changes for (?P[\w ]+) were rejected"), "{current_country} rejected new taxes for {product}", ), EventKind( "Product Tax", re.compile(rf"New taxes for (?P[\w ]+) were proposed"), "{current_country} proposed new taxes for {product}" ), ] def main(country): page = 1 has_unknown = False while True: for entry in feedparser.parse(f"https://www.erepublik.com/en/main/news/military/all/{country}/{page}/rss").entries: msg = entry["summary"] for kind in events: match = kind.regex.search(msg) if match: text = kind.format.format(**dict(match.groupdict(), **{"current_country": country})) print(f"{kind.name:<20} -||- {text:<80} -||- {entry['link']:<64} -||- {entry['published']}") break else: has_unknown = True break else: page += 1 if page > 5: break continue break if has_unknown: print(page, entry) raise ValueError(msg) if __name__ == "__main__": for c in sorted(COUNTRIES.values(), key=lambda _c: _c.id): if c.id == 71: main(c.link) print("Finished", c)