part 1 of the server builder complete

This commit is contained in:
Phillip Tarrant 2020-08-23 18:43:28 -04:00
parent a6c1a885d6
commit 6ec2f1c6ac
1444 changed files with 1017 additions and 281914 deletions

View File

@ -0,0 +1,210 @@
import os
import sys
import json
import time
import logging
from datetime import datetime
from app.classes.shared.helpers import helper
from app.classes.shared.console import console
from app.classes.shared.models import Servers
from app.classes.minecraft.server_props import ServerProps
logger = logging.getLogger(__name__)
try:
import requests
except ModuleNotFoundError as e:
logger.critical("Import Error: Unable to load {} module".format(e, e.name))
console.critical("Import Error: Unable to load {} module".format(e, e.name))
sys.exit(1)
class ServerJars:
def _get_api_result(self, call_url: str):
base_url = "https://serverjars.com"
full_url = "{base}{call_url}".format(base=base_url, call_url=call_url)
r = requests.get(full_url, timeout=2)
if r.status_code not in [200, 201]:
return {}
try:
api_data = json.loads(r.content)
except Exception as e:
logger.error("Unable to parse serverjar.com api result due to error: {}".format(e))
return {}
api_result = api_data.get('status')
api_response = api_data.get('response', {})
if api_result != "success":
logger.error("Api returned a failed status: {}".format(api_result))
return {}
return api_response
@staticmethod
def _read_cache():
cache_file = helper.serverjar_cache
cache = {}
try:
with open(cache_file, "r") as f:
cache = json.load(f)
except Exception as e:
logger.error("Unable to read serverjars.com cache file: {}".format(e))
return cache
def get_serverjar_data(self):
data = self._read_cache()
return data.get('servers')
@staticmethod
def _check_api_alive():
logger.info("Checking serverjars.com API status")
check_url = "https://serverjars.com/api/fetchTypes"
r = requests.get(check_url, timeout=2)
if r.status_code in [200, 201]:
logger.info("Serverjars.com API is alive")
return True
logger.error("unable to contact Serverjars.com api")
return False
def refresh_cache(self):
cache_file = helper.serverjar_cache
cache_old = helper.is_file_older_than_x_days(cache_file)
# debug override
# cache_old = True
# if the API is down... we bomb out
if not self._check_api_alive():
return False
logger.info("Checking Cache file age")
# if file is older than 1 day
if cache_old:
logger.info("Cache file is over 1 day old, refreshing")
now = datetime.now()
data = {
'last_refreshed': now.strftime("%m/%d/%Y, %H:%M:%S"),
'servers': {}
}
jar_types = self._get_server_type_list()
# for each jar type
for j in jar_types:
# for each server
for s in jar_types.get(j):
# jar versions for this server
versions = self._get_jar_details(s)
# add these versions (a list) to the dict with a key of the server type
data['servers'].update({
s: versions
})
# save our cache
try:
with open(cache_file, "w") as f:
f.write(json.dumps(data, indent=4))
logger.info("Cache file refreshed")
except Exception as e:
logger.error("Unable to update serverjars.com cache file: {}".format(e))
def _get_jar_details(self, jar_type='servers'):
url = '/api/fetchAll/{type}'.format(type=jar_type)
response = self._get_api_result(url)
temp = []
for v in response:
temp.append(v.get('version'))
time.sleep(.5)
return temp
def _get_server_type_list(self):
url = '/api/fetchTypes/'
response = self._get_api_result(url)
return response
def download_jar(self, server, version, path):
base_url = "https://serverjars.com/api/fetchJar/{server}/{version}".format(server=server, version=version)
r = requests.get(base_url, timeout=2)
if r.status_code in [200, 201]:
try:
with open(path, 'bw') as output:
output.write(r.content)
return True
except Exception as e:
logger.error("Unable to save jar to {path} due to error:{error}".format(path=path, error=e))
pass
logger.error("Got {} code from download, escaping".format(r.status_code))
return False
# todo: build server
def build_server(self, server: str, version: str, name: str, min_mem: int, max_mem: int, port: int):
server_id = helper.create_uuid()
server_dir = os.path.join(helper.servers_dir, server_id)
jar_file = "{server}-{version}.jar".format(server=server, version=version)
full_jar_path = os.path.join(server_dir, jar_file)
# make the dir - perhaps a UUID?
helper.ensure_dir_exists(server_dir)
# download the jar
self.download_jar(server, version, full_jar_path)
# todo: verify the MD5
# put data in the db
Servers.insert({
Servers.server_name: name,
Servers.server_uuid: server_id,
Servers.path: server_dir,
Servers.executable: jar_file,
Servers.execution_command: 'java -Xms{}G -Xmx{}G -jar /var/opt/minecraft/server/paperclip.jar nogui'.format(min_mem, max_mem),
Servers.auto_start: False,
Servers.auto_start_delay: 10,
Servers.crash_detection: False,
Servers.log_path:"{}/logs/latest.log".format(server_dir),
Servers.stop_command:'stop'
}).execute()
try:
# place a file in the dir saying it's owned by crafty
with open(os.path.join(server_dir, "crafty_managed.txt"), 'w') as f:
f.write("The server in this directory is managed by Crafty Controller.\n Leave this file alone please")
f.close()
# do a eula.txt
with open(os.path.join(server_dir, "eula.txt"), 'w') as f:
f.write("eula=true")
f.close()
# setup server.properties with the port
with open(os.path.join(server_dir, "server.properties"), "w") as f:
f.write("server_port={}".format(port))
f.close()
except Exception as e:
logger.error("Unable to create required server files due to :{}".format(e))
return False
return True
server_jar_obj = ServerJars()

View File

@ -1,6 +1,7 @@
import os import os
import sys import sys
import json import json
import time
import uuid import uuid
import string import string
import base64 import base64
@ -29,13 +30,28 @@ class Helpers:
def __init__(self): def __init__(self):
self.root_dir = os.path.abspath(os.path.curdir) self.root_dir = os.path.abspath(os.path.curdir)
self.config_dir = os.path.join(self.root_dir, 'app', 'config') self.config_dir = os.path.join(self.root_dir, 'app', 'config')
self.webroot = os.path.join(self.root_dir, 'app', 'frontend')
self.servers_dir = os.path.join(self.root_dir, 'servers')
self.session_file = os.path.join(self.root_dir, 'session.lock') self.session_file = os.path.join(self.root_dir, 'session.lock')
self.settings_file = os.path.join(self.root_dir, 'config.ini') self.settings_file = os.path.join(self.root_dir, 'config.ini')
self.webroot = os.path.join(self.root_dir, 'app', 'frontend')
self.db_path = os.path.join(self.root_dir, 'crafty.sqlite') self.db_path = os.path.join(self.root_dir, 'crafty.sqlite')
self.serverjar_cache = os.path.join(self.config_dir, 'serverjars.json')
self.passhasher = PasswordHasher() self.passhasher = PasswordHasher()
self.exiting = False self.exiting = False
def is_file_older_than_x_days(self, file, days=1):
if self.check_file_exists(file):
file_time = os.path.getmtime(file)
# Check against 24 hours
if (time.time() - file_time) / 3600 > 24 * days:
return True
else:
return False
logger.error("{} does not exits".format(file))
return False
def get_setting(self, section, key): def get_setting(self, section, key):
try: try:
@ -254,8 +270,7 @@ class Helpers:
return b64_bytes.decode("utf-8") return b64_bytes.decode("utf-8")
def create_uuid(self): def create_uuid(self):
id = str(uuid.uuid4()) return str(uuid.uuid4())
return self.base64_encode_string(id).replace("\n", '')
def ensure_dir_exists(self, path): def ensure_dir_exists(self, path):
""" """

View File

@ -63,6 +63,7 @@ class Host_Stats(BaseModel):
class Servers(BaseModel): class Servers(BaseModel):
server_id = AutoField() server_id = AutoField()
created = DateTimeField(default=datetime.datetime.now) created = DateTimeField(default=datetime.datetime.now)
server_uuid = CharField(default="")
server_name = CharField(default="Server") server_name = CharField(default="Server")
path = CharField(default="") path = CharField(default="")
executable = CharField(default="") executable = CharField(default="")
@ -139,9 +140,14 @@ class db_shortcuts:
def return_rows(self, query): def return_rows(self, query):
rows = [] rows = []
if query: try:
if query.count() > 0:
for s in query: for s in query:
rows.append(model_to_dict(s)) rows.append(model_to_dict(s))
except Exception as e:
logger.warning("Database Error: {}".format(e))
pass
return rows return rows
def get_all_defined_servers(self): def get_all_defined_servers(self):

View File

@ -11,6 +11,7 @@ from app.classes.web.tornado import webserver
from app.classes.minecraft import server_props from app.classes.minecraft import server_props
from app.classes.minecraft.stats import stats from app.classes.minecraft.stats import stats
from app.classes.minecraft.controller import controller from app.classes.minecraft.controller import controller
from app.classes.minecraft.serverjars import server_jar_obj
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -90,5 +91,13 @@ class TasksManager:
console.info("Stats collection frequency set to {stats} seconds".format(stats=stats_update_frequency)) console.info("Stats collection frequency set to {stats} seconds".format(stats=stats_update_frequency))
schedule.every(stats_update_frequency).seconds.do(stats.record_stats) schedule.every(stats_update_frequency).seconds.do(stats.record_stats)
@staticmethod
def serverjar_cache_refresher():
logger.info("Refreshing serverjars.com cache on start")
server_jar_obj.refresh_cache()
logger.info("Scheduling Serverjars.com cache refresh service every 12 hours")
schedule.every(12).hours.do(server_jar_obj.refresh_cache)
tasks_manager = TasksManager() tasks_manager = TasksManager()

View File

@ -8,7 +8,11 @@ logger = logging.getLogger(__name__)
class DefaultHandler(BaseHandler): class DefaultHandler(BaseHandler):
# Override prepare() instead of get() to cover all possible HTTP methods. # Override prepare() instead of get() to cover all possible HTTP methods.
def prepare(self): def prepare(self, page=None):
print(page)
if page is not None:
self.set_status(404) self.set_status(404)
self.render("public/404.html") self.render("public/404.html")
else:
self.redirect("/public/login")

View File

@ -40,27 +40,28 @@ class PublicHandler(BaseHandler):
self.clear_cookie("user") self.clear_cookie("user")
self.clear_cookie("user_data") self.clear_cookie("user_data")
error = bleach.clean(self.get_argument('error', "Invalid Login!"))
page_data = { page_data = {
'version': helper.get_version_string() 'version': helper.get_version_string(),
'error': error
} }
error = bleach.clean(self.get_argument('error', ""))
if error:
error_msg = "Invalid Login!"
else:
error_msg = ""
# sensible defaults # sensible defaults
template = "public/404.html" template = "public/404.html"
if page == "login": if page == "login":
template = "public/login.html" template = "public/login.html"
page_data['error'] = error_msg
elif page == 404:
template = "public/404.html"
elif page == "error":
template = "public/error.html"
# if we have no page, let's go to login # if we have no page, let's go to login
else: else:
template = "public/404.html" self.redirect('/public/login')
self.render(template, data=page_data) self.render(template, data=page_data)

View File

@ -1,18 +1,26 @@
import sys
import json import json
import logging import logging
import tornado.web
import tornado.escape
import bleach
from app.classes.shared.console import console from app.classes.shared.console import console
from app.classes.shared.models import Users, installer
from app.classes.web.base_handler import BaseHandler from app.classes.web.base_handler import BaseHandler
from app.classes.minecraft.controller import controller from app.classes.minecraft.controller import controller
from app.classes.shared.models import db_helper from app.classes.shared.models import db_helper, Servers
from app.classes.minecraft.serverjars import server_jar_obj
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
try:
import tornado.web
import tornado.escape
import bleach
except ModuleNotFoundError as e:
logger.critical("Import Error: Unable to load {} module".format(e, e.name))
console.critical("Import Error: Unable to load {} module".format(e, e.name))
sys.exit(1)
class ServerHandler(BaseHandler): class ServerHandler(BaseHandler):
@ -35,10 +43,44 @@ class ServerHandler(BaseHandler):
'hosts_data': db_helper.get_latest_hosts_stats() 'hosts_data': db_helper.get_latest_hosts_stats()
} }
# print(page_data['hosts_data'])
if page == "step1":
page_data['server_types'] = server_jar_obj.get_serverjar_data()
template = "server/wizard.html"
self.render(
template,
data=page_data
)
@tornado.web.authenticated
def post(self, page):
user_data = json.loads(self.get_secure_cookie("user_data"))
template = "public/404.html"
page_data = {
'version_data': "version_data_here",
'user_data': user_data,
}
print(page) print(page)
if page == "step1":
server = bleach.clean(self.get_argument('server', ''))
server_name = bleach.clean(self.get_argument('server_name', ''))
min_mem = bleach.clean(self.get_argument('min_memory', ''))
max_mem = bleach.clean(self.get_argument('max_memory', ''))
port = bleach.clean(self.get_argument('port', ''))
server_parts = server.split("|")
success = server_jar_obj.build_server(server_parts[0], server_parts[1],server_name,min_mem, max_mem, port)
if success:
self.redirect("/panel/dashboard")
self.render( self.render(
template, template,

View File

@ -3,7 +3,10 @@
"disable_existing_loggers": false, "disable_existing_loggers": false,
"formatters": { "formatters": {
"commander": { "commander": {
"format": "%(asctime)s - [Commander] - %(levelname)-8s - %(name)s - %(message)s" "format": "%(asctime)s - [Crafty] - %(levelname)-8s - %(name)s - %(message)s"
},
"tornado_access": {
"format": "%(asctime)s - [Tornado] - [Access] - %(levelname)s - %(message)s"
} }
}, },
@ -28,6 +31,14 @@
"filename": "logs/session.log", "filename": "logs/session.log",
"backupCount": 0, "backupCount": 0,
"encoding": "utf8" "encoding": "utf8"
},
"tornado_access_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"formatter": "tornado_access",
"filename": "logs/tornado-access.log",
"maxBytes": 10485760,
"backupCount": 20,
"encoding": "utf8"
} }
}, },
@ -36,6 +47,11 @@
"level": "INFO", "level": "INFO",
"handlers": ["main_file_handler", "session_file_handler"], "handlers": ["main_file_handler", "session_file_handler"],
"propagate": false "propagate": false
},
"tornado.access": {
"level": "INFO",
"handlers": ["tornado_access_file_handler"],
"propagate": false
} }
} }
} }

344
app/config/serverjars.json Normal file
View File

@ -0,0 +1,344 @@
{
"last_refreshed": "08/23/2020, 17:45:25",
"servers": {
"nukkitx": [
"1.14"
],
"pocketmine": [
"1.14",
"1.13",
"1.12",
"1.11",
"1.10",
"1.9",
"1.8",
"1.7",
"1.6",
"1.5",
"1.4"
],
"magma": [
"1.12.2"
],
"mohist": [
"1.12.2"
],
"travertine": [
"1.16",
"1.15",
"1.14",
"1.13",
"1.12",
"1.11",
"1.10",
"1.9",
"1.8",
"1.7"
],
"bungeecord": [
"1.16",
"1.15",
"1.14",
"1.13",
"1.12",
"1.11",
"1.10",
"1.9",
"1.8"
],
"velocity": [
"1.15",
"1.14",
"1.13",
"1.12",
"1.11",
"1.10",
"1.9",
"1.8"
],
"waterfall": [
"1.16",
"1.15",
"1.14",
"1.13",
"1.12",
"1.11",
"1.10",
"1.9",
"1.8"
],
"bukkit": [
"1.16.2",
"1.16.1",
"1.15.2",
"1.15.1",
"1.15",
"1.14.4",
"1.14.3",
"1.14.2",
"1.14.1",
"1.14",
"1.13.2",
"1.13.1",
"1.13",
"1.12.2",
"1.12.1",
"1.12",
"1.11.2",
"1.11.1",
"1.11",
"1.10.2",
"1.10",
"1.9.4",
"1.9.2",
"1.9",
"1.8.8",
"1.8"
],
"paper": [
"1.16.1",
"1.15.2",
"1.15.1",
"1.15",
"1.14.4",
"1.14.3",
"1.14.2",
"1.14.1",
"1.14",
"1.13.2",
"1.13.1",
"1.13",
"1.12.2",
"1.12.1",
"1.12",
"1.11.2",
"1.10.2",
"1.9.4",
"1.8.8"
],
"spigot": [
"1.16.2",
"1.16.1",
"1.15.2",
"1.15.1",
"1.15",
"1.14.4",
"1.14.3",
"1.14.2",
"1.14.1",
"1.14",
"1.13.2",
"1.13.1",
"1.13",
"1.12.2",
"1.12.1",
"1.12",
"1.11.2",
"1.11.1",
"1.11",
"1.10.2",
"1.10",
"1.9.4",
"1.9.2",
"1.9",
"1.8.8"
],
"snapshot": [
"1.16pre8",
"1.16pre7",
"1.16pre6",
"1.16pre5",
"1.16pre4",
"1.16pre3",
"1.16pre2",
"1.16pre1",
"1.1620w30a",
"1.1620w29a",
"1.1620w28a",
"1.1620w27a",
"1.1620w22a",
"1.1620w21a",
"1.1620w20b",
"1.1620w20a",
"1.1620w19a",
"1.1620w18a",
"1.1620w17a",
"1.1620w16a",
"1.1620w15a",
"1.1620w14a",
"1.1620w14infinite",
"1.1620w13b",
"1.1620w13a",
"1.1620w12a",
"1.16rc1",
"1.1620w11a",
"1.1620w10a",
"1.1620w09a",
"1.1620w08a",
"1.1620w07a",
"1.16.2rc2",
"1.16.2rc1",
"1.1620w06a",
"1.16.2pre3",
"1.16.2pre2",
"1.16.2pre1",
"1.16.2",
"1.161.16.1",
"1.16.1",
"1.16",
"1.15pre7",
"1.15pre6",
"1.15pre5",
"1.15pre4",
"1.15pre3",
"1.15pre2",
"1.15pre1",
"1.1519w46b",
"1.1519w46a",
"1.1519w45b",
"1.1519w45a",
"1.1519w44a",
"1.1519w42a",
"1.1519w41a",
"1.1519w40a",
"1.1519w39a",
"1.1519w38b",
"1.1519w38a",
"1.1519w37a",
"1.1519w36a",
"1.1519w35a",
"1.1519w34a",
"1.15.2pre2",
"1.15.2pre1",
"1.15.1pre1",
"1.14pre5",
"1.14pre4",
"1.14pre3",
"1.14pre2",
"1.14pre1",
"1.1419w14b",
"1.1419w14a",
"1.1419w13b",
"1.1419w13a",
"1.1419w12b",
"1.1419w12a",
"1.1419w11b",
"1.1419w11a",
"1.1419w09a",
"1.1419w08b",
"1.1419w08a",
"1.1419w07a",
"1.1419w06a",
"1.1419w05a",
"1.1419w04b",
"1.1419w04a",
"1.1419w03b",
"1.1419w03a",
"1.1419w03c",
"1.1419w02a",
"1.1418w50a",
"1.1418w49a",
"1.1418w48b",
"1.1418w48a",
"1.1418w47b",
"1.1418w47a",
"1.1418w46a",
"1.1418w45a",
"1.1418w44a",
"1.1418w43b",
"1.1418w43a",
"1.1418w43c",
"1.14.4pre7",
"1.14.4pre6",
"1.14.4pre5",
"1.14.4pre4",
"1.14.4pre3",
"1.14.4pre2",
"1.14.4pre1",
"1.14.3pre4",
"1.14.3pre3",
"1.14.3pre2",
"1.14.3pre1",
"1.14.2pre4",
"1.14.2pre3",
"1.14.2pre2",
"1.14.2pre1",
"1.14.1pre2",
"1.14.1pre1"
],
"vanilla": [
"1.16.2",
"1.16.1",
"1.16",
"1.15.2",
"1.15.1",
"1.15",
"1.14.4",
"1.14.3",
"1.14.2",
"1.14.1",
"1.14",
"1.13.2",
"1.13.1",
"1.13",
"1.12.2",
"1.12.1",
"1.12",
"1.11.2",
"1.11.1",
"1.11",
"1.10.2",
"1.10.1",
"1.10",
"1.9.4",
"1.9.3",
"1.9.2",
"1.9.1",
"1.9",
"1.8.8",
"1.8.7",
"1.8.6",
"1.8.5",
"1.8.4",
"1.8.3",
"1.8.2",
"1.8.1",
"1.8",
"1.7.10",
"1.7.9",
"1.7.8",
"1.7.7",
"1.7.6",
"1.7.5",
"1.7.4",
"1.7.3",
"1.7.2",
"1.7.1",
"1.7",
"1.6.4",
"1.6.3",
"1.6.2",
"1.6.1",
"1.6",
"1.5.2",
"1.5.1",
"1.5",
"1.4.7",
"1.4.6",
"1.4.5",
"1.4.4",
"1.4.3",
"1.4.2",
"1.4.1",
"1.4",
"1.3.2",
"1.3.1",
"1.3",
"1.2.5",
"1.2.4",
"1.2.3",
"1.2.2",
"1.2.1"
]
}
}

View File

@ -0,0 +1,9 @@
.select-css option {
background-color: #1C1E2F;
color: white
}
.select-css option:checked {
background-color: #1C1E2F;
color: white
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 966 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

View File

@ -1,13 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="35" height="35" viewBox="0 0 35 35">
<defs>
<circle id="a" cx="17.5" cy="17.5" r="17.5"/>
</defs>
<g fill="none" fill-rule="evenodd">
<mask id="b" fill="#fff">
<use xlink:href="#a"/>
</mask>
<use fill="#0DC26D" xlink:href="#a"/>
<path fill="#FFF" d="M17.5 0H35v17.5H17.5z" mask="url(#b)"/>
<path fill="#EFF3F6" d="M17.5 17.5H35V35H17.5z" mask="url(#b)" opacity=".5"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 546 B

View File

@ -1 +0,0 @@
<svg id="SvgjsSvg1011" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" width="18" height="19" viewBox="0 0 18 19"><title>Shape</title><desc>Created with Avocode.</desc><defs id="SvgjsDefs1012"></defs><path id="SvgjsPath1013" d="M603.64 503.84C603.64 503.2 603.58 502.59 603.48 502L595 502L595 505.48L599.84 505.48C599.64 506.61 599 507.56 598.0500000000001 508.20000000000005L598.0500000000001 510.46000000000004L600.96 510.46000000000004C602.6600000000001 508.89000000000004 603.64 506.58000000000004 603.64 503.84000000000003Z " fill="#4285f4" fill-opacity="1" transform="matrix(1,0,0,1,-586,-495)"></path><path id="SvgjsPath1014" d="M595.04 513.29C597.4699999999999 513.29 599.51 512.48 601 511.10999999999996L598.09 508.84999999999997C597.2800000000001 509.39 596.25 509.71 595.0400000000001 509.71C592.7 509.71 590.71 508.13 590.0100000000001 506L587.0000000000001 506L587.0000000000001 508.33C588.4800000000001 511.27 591.5200000000001 513.29 595.0400000000001 513.29Z " fill="#34a853" fill-opacity="1" transform="matrix(1,0,0,1,-586,-495)"></path><path id="SvgjsPath1015" d="M589.96 505.75C589.7800000000001 505.21 589.6800000000001 504.64 589.6800000000001 504.04C589.6800000000001 503.45000000000005 589.7800000000001 502.87 589.96 502.33000000000004L589.96 500.00000000000006L586.96 500.00000000000006C586.35 501.2200000000001 586 502.59000000000003 586 504.0400000000001C586 505.49000000000007 586.35 506.87000000000006 586.96 508.0800000000001Z " fill="#fbbc05" fill-opacity="1" transform="matrix(1,0,0,1,-586,-495)"></path><path id="SvgjsPath1016" d="M595.04 498.58C596.36 498.58 597.55 499.03 598.48 499.93L601.0600000000001 497.34000000000003C599.5100000000001 495.89000000000004 597.47 495.00000000000006 595.0400000000001 495.00000000000006C591.5200000000001 495.00000000000006 588.4800000000001 497.02000000000004 587.0000000000001 499.96000000000004L590.0100000000001 502.29C590.7100000000002 500.16 592.7000000000002 498.58000000000004 595.0400000000001 498.58000000000004Z " fill="#ea4335" fill-opacity="1" transform="matrix(1,0,0,1,-586,-495)"></path></svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 829 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 758 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 674 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 683 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 744 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 872 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 923 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 443 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 476 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Some files were not shown because too many files have changed in this diff Show More