diff --git a/.gitignore b/.gitignore index f81d38c..b946644 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ ## VENV folders and files bin include -lib +lib* __pycache__ pyvenv.cfg diff --git a/README.md b/README.md index 398ee66..819843f 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,14 @@ http://flagsmashupbot.pythonanywhere.com/ -![alt text](https://i.imgur.com/LSepqer.png) +![Twitter Screenshot](https://i.imgur.com/8SD4piZ.png) https://twitter.com/FlagsMashupBot ------------------------------------------------------- ## Prerequisites - Python3 - - Pycairo's [required files in your machine](https://pycairo.readthedocs.io/en/latest/getting_started.html) + - Cairo's [required files in your machine](https://cairosvg.org/documentation/#installation) ### Clone the repo ```bash @@ -22,7 +22,7 @@ git clone https://github.com/antooro/FlagsMashupBot ### Start a virtual environment **LINUX/OSX**: Inside the repo folder ```bash -python -m ./ # starts the venv in the current folder +python3 -m venv ./ # starts the venv in the current folder source bin/activate # On LINUX or OSX .\Scripts\activate # ONLY Windows ``` diff --git a/countries.db b/countries.db index c7793dc..4a55776 100644 Binary files a/countries.db and b/countries.db differ diff --git a/formatsvg.py b/formatsvg.py index 89e2429..44c4b08 100644 --- a/formatsvg.py +++ b/formatsvg.py @@ -1,18 +1,31 @@ -import requests -import random -from PIL import Image -from collections import Counter -from names import NameJoiner -from bs4 import BeautifulSoup +import itertools +import math import os +import random import shutil -import cairosvg import sqlite3 -import itertools -import math +from collections import Counter + +import cairosvg +import requests +from PIL import Image +from bs4 import BeautifulSoup + +from names import NameJoiner + +API_URL = 'https://restcountries.com/v3.1' class CountryMixer: + def __init__(self): + self.templateUrl = None + self.flags_info = None + self.svgText = None + self.template3Code = None + self.countries = None + self.second_country = None + self.first_country = None + def rgb2hex(self, color): r, g, b = color code = "#{:02x}{:02x}{:02x}".format(r, g, b) @@ -26,7 +39,7 @@ def smallerHex(self, bigHex): def getCountry(self, code): for n in self.flags_info: - if n['alpha2Code'] == code: + if n['cca2'] == code: country = n print(country['name']) return country @@ -36,12 +49,10 @@ def getNeighbours(self): while not hasCountries: first_country = random.choice(self.flags_info) - country_flag_code = first_country['alpha3Code'] - print(country_flag_code, first_country['borders']) - if len(first_country['borders']) > 0: + if 'borders' in first_country: frontier = random.choice(first_country['borders']) for flag_info in self.flags_info: - if flag_info['alpha3Code'] == frontier: + if flag_info['cca3'] == frontier: second_country = flag_info if first_country and second_country: @@ -51,13 +62,13 @@ def getNeighbours(self): self.second_country = second_country self.countries = (self.first_country, self.second_country) for country in self.countries: - self.downloadPNGFlag(country["alpha3Code"]) + self.downloadPNGFlag(country['flags']['svg'], country["cca3"]) def updateDbWithBase(self, template): conn = sqlite3.connect('countries.db') c = conn.cursor() first_country, second_country = sorted( - [self.first_country['alpha2Code'], self.second_country['alpha2Code']]) + [self.first_country['cca2'], self.second_country['cca2']]) c.execute('update countries set base=(?) where first_country=(?) and second_country=(?) and base is null', (template, first_country, second_country)) @@ -66,8 +77,7 @@ def updateDbWithBase(self, template): def insertCountries(self): conn = sqlite3.connect('countries.db') c = conn.cursor() - first_country, second_country = sorted( - [self.first_country['alpha2Code'], self.second_country['alpha2Code']]) + first_country, second_country = sorted([self.first_country['cca2'], self.second_country['cca2']]) print(first_country, second_country) c.execute('insert into countries values (?,?,?)', (first_country, second_country, None)) @@ -87,8 +97,8 @@ def checkMashupValid(self): conn = sqlite3.connect('countries.db') c = conn.cursor() first_country, second_country = sorted( - [self.first_country['alpha2Code'], self.second_country['alpha2Code']]) - if first_country == "NU" or second_country == "NU": + [self.first_country['cca2'], self.second_country['cca2']]) + if "NU" in [first_country, second_country]: # why? return False print(first_country, second_country) c.execute('select * from countries where first_country=? and second_country=?', @@ -98,68 +108,56 @@ def checkMashupValid(self): if len(rows) == 1 and rows[0][2]: co = Counter(rows[0]) self.template3Code = co.most_common()[-1][0] - if self.template3Code == self.first_country['alpha2Code']: - self.template3Code = self.first_country['alpha3Code'] + if self.template3Code == self.first_country['cca2']: + self.template3Code = self.first_country['cca3'] else: - self.template3Code = self.second_country['alpha3Code'] + self.template3Code = self.second_country['cca3'] print(self.template3Code) - return True - elif len(rows) < 1: - self.template3Code = None - return True else: self.template3Code = None - - return False + return len(rows) < 1 def getFullFlagsInfoJSON(self): - info = requests.get("https://restcountries.eu/rest/v2/all") + info = requests.get(f"{API_URL}/all") if info.status_code != 200: raise RuntimeError("Can't get full flags info") return info.json() def chooseRandomFlag(self, alreadyChoosen=None): - while True: flag = random.choice(self.flags_info) - if flag['alpha3Code'] != alreadyChoosen: + if flag['cca3'] != alreadyChoosen: return flag - def downloadPNGFlag(self, alpha3Code): - r = requests.get( - f"https://restcountries.eu/data/{alpha3Code.lower()}.svg") - print(alpha3Code) - cairosvg.svg2png(bytestring=r.text, - write_to=f'{alpha3Code.lower()}.png') + def downloadPNGFlag(self, url, alpha3Code): + r = requests.get(url) + cairosvg.svg2png(bytestring=r.text, write_to=f'{alpha3Code.lower()}.png') def randomlyDownloadFlags(self): - self.first_country = self.chooseRandomFlag() self.second_country = self.chooseRandomFlag() self.countries = (self.first_country, self.second_country) for country in self.countries: - self.downloadPNGFlag(country["alpha3Code"]) + self.downloadPNGFlag(country['flags']['svg'], country["cca3"]) def getFlagsEmojis(self): emojis = [] for country in self.countries: - country_alpha_code = country['alpha2Code'] - emoji = (chr( - ord(country_alpha_code[0]) + 127397) + chr(ord(country_alpha_code[1]) + 127397)) + country_alpha_code = country['cca2'] + emoji = (chr(ord(country_alpha_code[0]) + 127397) + chr(ord(country_alpha_code[1]) + 127397)) emojis.append(emoji) return emojis def getFlagsSortedColors(self): - flagsSortedColors = [] for country in self.countries: - img = Image.open(f'{country["alpha3Code"].lower()}.png') + img = Image.open(f'{country["cca3"].lower()}.png') width, height = img.size limit = ((width * height) * .01) colors = img.convert('RGBA').getcolors( @@ -167,8 +165,7 @@ def getFlagsSortedColors(self): colors = sorted(colors, key=lambda x: x[0], reverse=True) colors = [c for c in colors if c[1][3] != 0] - colorb1 = [self.rgb2hex(color[1][:3]) - for color in colors[:5] if color[0] > limit] + colorb1 = [self.rgb2hex(color[1][:3]) for color in colors[:5] if color[0] > limit] combinations = itertools.combinations(colorb1, 2) @@ -202,16 +199,17 @@ def selectTemplateAndColors(self, nameColorList): if random.randint(0, 2) == 0: template, colors = colors, template - if self.isAlreadyDone(self.countries[template]["alpha2Code"], self.countries[colors]["alpha2Code"]): + if self.isAlreadyDone(self.countries[template]["cca2"], self.countries[colors]["cca2"]): template, colors = colors, template if self.first_country is not self.second_country: - self.updateDbWithBase(self.countries[template]["alpha2Code"]) + self.updateDbWithBase(self.countries[template]["cca2"]) - if not self.template3Code: - self.template3Code = self.countries[template]['alpha3Code'] - templateSVG = requests.get( - f"https://restcountries.eu/data/{self.template3Code.lower()}.svg") + if not self.templateUrl or not self.template3Code: + self.templateUrl = self.countries[template]['flags']['svg'] + self.template3Code = self.countries[template]['cca3'] + + templateSVG = requests.get(self.templateUrl) for i in nameColorList: @@ -278,9 +276,7 @@ def clean(self, text): if differs: print("They differ") - data = str(svg).replace("", - "\n").replace("", "") - text = data + text = str(svg).replace("", "\n").replace("", "") return text @@ -288,8 +284,7 @@ def changeColors(self, changes): self.svgText = self.clean(self.svgText) for new, old in changes.items(): self.svgText = self.svgText.replace(old, new.replace('#', 'ç')) - self.svgText = self.svgText.replace( - old.upper(), new.replace('#', 'ç')) + self.svgText = self.svgText.replace(old.upper(), new.replace('#', 'ç')) for new, old in changes.items(): self.svgText = self.svgText.replace( @@ -300,38 +295,18 @@ def changeColors(self, changes): self.svgText = self.svgText.replace('ç', '#') def calculateNames(self): - name1 = self.first_country['name'] - name2 = self.second_country['name'] - - if "(" in name1: - p_temp = name1.split("(") - name1 = p_temp[1].replace(")", "") + " " + p_temp[0] - - if "(" in name2: - p_temp = name2.split("(") - name2 = p_temp[1].replace(")", "") + " " + p_temp[0] + name1 = self.first_country['name']['common'] + name2 = self.second_country['name']['common'] - if "," in name1: - p_temp = name1.split(", ") - name1 = p_temp[1] + " " + p_temp[0] - - if "," in name2: - p_temp = name2.split(", ") - name2 = p_temp[1] + " " + p_temp[0] - - self.first_country['name'] = name1 - self.second_country['name'] = name2 + if name1 == name2: + return name1 + ' 2' if len(name2.split()) > 1: - name = (" ".join(name2.split()[:-1]) + " " + name1.split()[-1]) + return " ".join(name2.split()[:-1]) + " " + name1.split()[-1] elif len(name1.split()) > 1: - name = (" ".join(name1.split()[:-1]) + " " + name2.split()[-1]) + return " ".join(name1.split()[:-1]) + " " + name2.split()[-1] else: - name = NameJoiner( - self.first_country['name'], self.second_country['name']).join() - if name1 == name2: - name = name1 + " 2" - return name + return NameJoiner(self.first_country['name']['common'], self.second_country['name']['common']).join() def saveToPNG(self): image = Image.open(f'{self.template3Code.lower()}.png') @@ -347,7 +322,7 @@ def saveToPNG(self): if fileSize < limit_kb: uploaded = True else: - bigger = bigger * 1.25 + bigger *= 1.25 def mixFlags(self): @@ -356,19 +331,16 @@ def mixFlags(self): print(colorb1, len(colorb1)) print(colorb2, len(colorb2)) - template, colors = self.selectTemplateAndColors( - [(0, colorb1), (1, colorb2)]) + template, colors = self.selectTemplateAndColors([(0, colorb1), (1, colorb2)]) self.svgText = template self.changeColors(colors) self.saveToPNG() def removePNGs(self): - i = 1 - for country_data in self.countries: + for index, country_data in enumerate(self.countries, 1): try: - filePath = f'{country_data["alpha3Code"].lower()}.png' - flagPath = f'flag{i}.png' - i = i + 1 + filePath = f'{country_data["cca3"].lower()}.png' + flagPath = f'flag{index}.png' shutil.move(filePath, flagPath) except: print("Unable to delete", filePath) @@ -386,8 +358,8 @@ def manuallyDownloadFlags(self, alpha3CodeFlag1=None, alpha3CodeFlag2=None): self.countries = (self.first_country, self.second_country) - self.downloadPNGFlag(self.first_country["alpha3Code"]) - self.downloadPNGFlag(self.second_country["alpha3Code"]) + self.downloadPNGFlag(self.first_country['flags']['svg'], self.first_country["cca3"]) + self.downloadPNGFlag(self.second_country['flags']['svg'], self.second_country["cca3"]) def main(self): self.flags_info = self.getFullFlagsInfoJSON() @@ -405,13 +377,13 @@ def main(self): self.insertCountries() self.mixFlags() print("Base is " + self.template3Code) - print(self.first_country['alpha3Code'], - self.second_country['alpha3Code']) + print(self.first_country['cca3'], + self.second_country['cca3']) name = self.calculateNames() print(name) self.removePNGs() - return [self.first_country["name"], self.second_country["name"]], self.getFlagsEmojis(), name + return [self.first_country["name"]['common'], self.second_country["name"]['common']], self.getFlagsEmojis(), name c = CountryMixer() diff --git a/requirements.txt b/requirements.txt index e8264a0..723a2fc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,20 +1,17 @@ -b64==0.4 -beautifulsoup4==4.9.3 -bs4==0.0.1 -cached-properties==0.7.4 -cairocffi==1.2.0 +beautifulsoup4==4.10.0 +cairocffi==1.3.0 CairoSVG==2.5.2 -certifi==2020.12.5 -cffi==1.14.5 -chardet==4.0.0 +certifi==2021.10.8 +cffi==1.15.0 +charset-normalizer==2.0.10 cssselect2==0.4.1 defusedxml==0.7.1 -idna==2.10 -lxml==4.6.3 -Pillow==8.3.2 -pycparser==2.20 -requests==2.25.1 -soupsieve==2.2.1 -tinycss2==1.1.0 -urllib3==1.26.5 +idna==3.3 +lxml==4.7.1 +Pillow==9.0.0 +pycparser==2.21 +requests==2.27.1 +soupsieve==2.3.1 +tinycss2==1.1.1 +urllib3==1.26.8 webencodings==0.5.1