- [nexus] Refactoring
- [nexus] Switch bot - [bot] Added extra receivers functionality GitOrigin-RevId: 68fc32d3e79ff411758f54f435fe8680fc42dead
144
WORKSPACE
@ -17,34 +17,34 @@ http_archive(
|
||||
# ToDo: wait for https://github.com/bazelbuild/rules_docker/pull/1638
|
||||
http_archive(
|
||||
name = "io_bazel_rules_docker",
|
||||
sha256 = "5aa15ff7a83f8de8ff0346bd8274fb82eec52c947106a066dc190c2624ec1cb4",
|
||||
strip_prefix = "rules_docker-aefbc69e5f758403d50f789eee55b30a3d947418",
|
||||
sha256 = "c2a283bea1ea30a3ceb9e5388a4c8c8eef68a815ac86f1d381f9d35cdee57f1b",
|
||||
strip_prefix = "rules_docker-46d29e34399a992087c857b13d8dcb8ec80dfd85",
|
||||
urls = [
|
||||
"https://github.com/the-superpirate/rules_docker/archive/aefbc69e5f758403d50f789eee55b30a3d947418.tar.gz",
|
||||
"https://github.com/the-superpirate/rules_docker/archive/46d29e34399a992087c857b13d8dcb8ec80dfd85.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
sha256 = "a160d9ac88f2aebda2aa995de3fa3171300c076f06ad1d7c2e1385728b8442fa",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/3.4.1/rules_nodejs-3.4.1.tar.gz"],
|
||||
sha256 = "f7037c8e295fdc921f714962aee7c496110052511e2b14076bd8e2d46bc9819c",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/4.4.5/rules_nodejs-4.4.5.tar.gz"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_k8s",
|
||||
sha256 = "c1c5a692ec994e99e9e7e77ae693086074d6dedfe72e6930efbcc66d30264032",
|
||||
strip_prefix = "rules_k8s-f1c6399cdd691b7aca90073398e8f690ec8992c6",
|
||||
sha256 = "a08850199d6900328ef899906717fb1dfcc6cde62701c63725748b2e6ca1d5d9",
|
||||
strip_prefix = "rules_k8s-d05cbea5c56738ef02c667c10951294928a1d64a",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_k8s/archive/f1c6399cdd691b7aca90073398e8f690ec8992c6.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_k8s/archive/d05cbea5c56738ef02c667c10951294928a1d64a.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_rust",
|
||||
sha256 = "d10dd5581f66ee169071ee06d52c52c8c7ca7467ac6266e301c0820d289b0f0b",
|
||||
strip_prefix = "rules_rust-336e1934b07211fb8736c19749919ef94df4df68",
|
||||
sha256 = "30c1b40d77a262e3f7dba6e4267fe4695b5eb1e68debc6aa06c3e09d429ae19a",
|
||||
strip_prefix = "rules_rust-0.1.0",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_rust/archive/336e1934b07211fb8736c19749919ef94df4df68.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_rust/archive/0.1.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@ -67,40 +67,17 @@ http_archive(
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_proto",
|
||||
sha256 = "aa1ee19226f707d44bee44c720915199c20c84a23318bb0597ed4e5c873ccbd5",
|
||||
strip_prefix = "rules_proto-40298556293ae502c66579620a7ce867d5f57311",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_proto/archive/40298556293ae502c66579620a7ce867d5f57311.tar.gz",
|
||||
],
|
||||
name = "rules_proto_grpc",
|
||||
sha256 = "507e38c8d95c7efa4f3b1c0595a8e8f139c885cb41a76cab7e20e4e67ae87731",
|
||||
strip_prefix = "rules_proto_grpc-4.1.1",
|
||||
urls = ["https://github.com/rules-proto-grpc/rules_proto_grpc/archive/4.1.1.tar.gz"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
sha256 = "b228318a786d99b665bc83bd6cdb81512cae5f8eb15e8cd19f9956604b8939f5",
|
||||
strip_prefix = "rules_python-a4a1ccffc666db5376342789ad021a943fb84256",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_python/archive/a4a1ccffc666db5376342789ad021a943fb84256.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "subpar",
|
||||
sha256 = "481233d60c547e0902d381cd4fb85b63168130379600f330821475ad234d9336",
|
||||
strip_prefix = "subpar-9fae6b63cfeace2e0fb93c9c1ebdc28d3991b16f",
|
||||
urls = [
|
||||
"https://github.com/google/subpar/archive/9fae6b63cfeace2e0fb93c9c1ebdc28d3991b16f.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "cython",
|
||||
build_file = "@com_github_grpc_grpc//third_party:cython.BUILD",
|
||||
sha256 = "e2e38e1f0572ca54d6085df3dec8b607d20e81515fb80215aed19c81e8fe2079",
|
||||
strip_prefix = "cython-0.29.21",
|
||||
urls = [
|
||||
"https://github.com/cython/cython/archive/0.29.21.tar.gz",
|
||||
],
|
||||
sha256 = "15f84594af9da06750ceb878abbf129241421e3abbd6e36893041188db67f2fb",
|
||||
strip_prefix = "rules_python-0.7.0",
|
||||
urls = ["https://github.com/bazelbuild/rules_python/archive/0.7.0.tar.gz"],
|
||||
)
|
||||
|
||||
# Images Install
|
||||
@ -109,37 +86,38 @@ load("//images:install.bzl", "images_install")
|
||||
|
||||
images_install()
|
||||
|
||||
# Go
|
||||
|
||||
load("//rules/go:setup.bzl", "go_setup")
|
||||
|
||||
go_setup()
|
||||
|
||||
load("//rules/go:install.bzl", "go_install")
|
||||
|
||||
go_install()
|
||||
|
||||
# Python
|
||||
register_toolchains("//rules/python:py_toolchain")
|
||||
|
||||
load("@rules_python//python:pip.bzl", "pip_install")
|
||||
load("@rules_python//python:pip.bzl", "pip_parse")
|
||||
|
||||
pip_install(
|
||||
pip_parse(
|
||||
name = "pip_modules",
|
||||
requirements = "//rules/python:requirements.txt",
|
||||
requirements_lock = "//rules/python:requirements-lock.txt",
|
||||
)
|
||||
|
||||
load("@pip_modules//:requirements.bzl", "install_deps")
|
||||
|
||||
install_deps()
|
||||
|
||||
# Proto / gRPC
|
||||
|
||||
http_archive(
|
||||
name = "rules_proto_grpc",
|
||||
sha256 = "7954abbb6898830cd10ac9714fbcacf092299fda00ed2baf781172f545120419",
|
||||
strip_prefix = "rules_proto_grpc-3.1.1",
|
||||
urls = ["https://github.com/rules-proto-grpc/rules_proto_grpc/archive/3.1.1.tar.gz"],
|
||||
)
|
||||
|
||||
load("@rules_proto_grpc//:repositories.bzl", "rules_proto_grpc_repos", "rules_proto_grpc_toolchains")
|
||||
|
||||
rules_proto_grpc_toolchains()
|
||||
|
||||
rules_proto_grpc_repos()
|
||||
|
||||
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
|
||||
|
||||
rules_proto_dependencies()
|
||||
|
||||
rules_proto_toolchains()
|
||||
|
||||
load("@rules_proto_grpc//js:repositories.bzl", "js_repos")
|
||||
|
||||
js_repos()
|
||||
@ -160,28 +138,11 @@ maven_fetch_remote_artifacts()
|
||||
|
||||
# Rust
|
||||
|
||||
load("@rules_rust//rust:repositories.bzl", "rust_repository_set")
|
||||
load("@rules_rust//rust:repositories.bzl", "rust_repositories")
|
||||
|
||||
rust_version = "1.51.0"
|
||||
|
||||
rustfmt_version = "1.4.20"
|
||||
|
||||
rust_repository_set(
|
||||
name = "rust_linux_x86_64",
|
||||
edition = "2018",
|
||||
exec_triple = "x86_64-unknown-linux-gnu",
|
||||
extra_target_triples = ["wasm32-unknown-unknown"],
|
||||
rustfmt_version = rustfmt_version,
|
||||
version = rust_version,
|
||||
)
|
||||
|
||||
rust_repository_set(
|
||||
name = "rust_darwin_x86_64",
|
||||
edition = "2018",
|
||||
exec_triple = "x86_64-apple-darwin",
|
||||
extra_target_triples = ["wasm32-unknown-unknown"],
|
||||
rustfmt_version = rustfmt_version,
|
||||
version = rust_version,
|
||||
rust_repositories(
|
||||
edition = "2021",
|
||||
version = "1.59.0",
|
||||
)
|
||||
|
||||
load("//rules/rust:crates.bzl", "raze_fetch_remote_crates")
|
||||
@ -192,17 +153,8 @@ raze_fetch_remote_crates()
|
||||
load("@build_bazel_rules_nodejs//:index.bzl", "node_repositories", "yarn_install")
|
||||
|
||||
node_repositories(
|
||||
node_repositories = {
|
||||
"15.5.1-darwin_amd64": ("node-v15.5.1-darwin-x64.tar.gz", "node-v15.5.1-darwin-x64", "4507dab0481b0b5374b5758b1eba7d105c8cbcb173548119b04d9ef7d9f1d40f"),
|
||||
"15.5.1-linux_amd64": ("node-v15.5.1-linux-x64.tar.xz", "node-v15.5.1-linux-x64", "dbc41a611d99aedf2cfd3d0acc50759a6b9084c7447862e990f51958d4a7aa41"),
|
||||
"15.5.1-windows_amd64": ("node-v15.5.1-win-x64.zip", "node-v15.5.1-win-x64", "e1f826f9647fc7058b48c669991956a427fe4b6ccefa415a18b41715483f958d"),
|
||||
"15.5.1-linux_s390x": ("node-v15.5.1-linux-s390x.tar.gz", "node-v15.5.1-linux-s390x", "e05f949ea11e2aafc08a7972c0f41a11a3628762e857d44965e0605d3bcd143f"),
|
||||
"15.5.1-linux_arm64": ("node-v15.5.1-linux-arm64.tar.gz", "node-v15.5.1-linux-arm64", "a2d14db86c6f8a070f227940ea44a3409966f6bed14df0ec6f676fe2e2f601c9"),
|
||||
},
|
||||
node_version = "15.5.1",
|
||||
package_json = ["//rules/nodejs:package.json"],
|
||||
preserve_symlinks = True,
|
||||
yarn_version = "1.22.4",
|
||||
)
|
||||
|
||||
yarn_install(
|
||||
@ -227,17 +179,6 @@ container_repositories()
|
||||
|
||||
load("@io_bazel_rules_docker//repositories:deps.bzl", container_deps = "deps")
|
||||
|
||||
# ToDo: temorary fix as registry was broken at 24.04.2021
|
||||
load("@bazel_gazelle//:deps.bzl", "go_repository")
|
||||
|
||||
go_repository(
|
||||
name = "com_github_google_go_containerregistry",
|
||||
importpath = "github.com/google/go-containerregistry",
|
||||
strip_prefix = "google-go-containerregistry-8a28419",
|
||||
type = "tar.gz",
|
||||
urls = ["https://api.github.com/repos/google/go-containerregistry/tarball/8a2841911ffee4f6892ca0083e89752fb46c48dd"], # v0.1.4
|
||||
)
|
||||
|
||||
container_deps()
|
||||
|
||||
load("@io_bazel_rules_docker//repositories:py_repositories.bzl", "py_deps")
|
||||
@ -259,7 +200,7 @@ rust_image_repos()
|
||||
|
||||
# K8s
|
||||
|
||||
load("@io_bazel_rules_k8s//k8s:k8s.bzl", "k8s_repositories")
|
||||
load("@io_bazel_rules_k8s//k8s:k8s.bzl", "k8s_defaults", "k8s_repositories")
|
||||
|
||||
k8s_repositories()
|
||||
|
||||
@ -267,6 +208,11 @@ load("@io_bazel_rules_k8s//k8s:k8s_go_deps.bzl", k8s_go_deps = "deps")
|
||||
|
||||
k8s_go_deps()
|
||||
|
||||
k8s_defaults(
|
||||
name = "k8s_deploy",
|
||||
image_chroot = "registry.infra.svc.cluster.local",
|
||||
)
|
||||
|
||||
# Miscellaneous
|
||||
|
||||
load("//rules/misc:setup.bzl", "rules_misc_setup_internal")
|
||||
|
@ -15,7 +15,6 @@ py3_image(
|
||||
"*.py",
|
||||
"configs/**/*.py",
|
||||
"daemons/**/*.py",
|
||||
"models/**",
|
||||
"proto/**",
|
||||
"services/**",
|
||||
],
|
||||
@ -36,8 +35,8 @@ py3_image(
|
||||
requirement("grpcio"),
|
||||
requirement("pypika"),
|
||||
requirement("uvloop"),
|
||||
"//idm/api/proto:idm_grpc_py",
|
||||
"//idm/api/proto:idm_proto_py",
|
||||
"//idm/api/proto:grpc_py",
|
||||
"//idm/api/proto:proto_py",
|
||||
"//library/aiogrpctools",
|
||||
requirement("aiokit"),
|
||||
"//library/aiopostgres",
|
||||
@ -54,7 +53,7 @@ container_push(
|
||||
name = "push-testing",
|
||||
format = "Docker",
|
||||
image = ":image",
|
||||
registry = "registry.example.com",
|
||||
registry = "registry.infra.svc.cluster.local",
|
||||
repository = "idm-api",
|
||||
tag = "testing",
|
||||
)
|
||||
@ -63,7 +62,7 @@ container_push(
|
||||
name = "push-latest",
|
||||
format = "Docker",
|
||||
image = ":image",
|
||||
registry = "registry.example.com",
|
||||
registry = "registry.infra.svc.cluster.local",
|
||||
repository = "idm-api",
|
||||
tag = "latest",
|
||||
)
|
||||
|
@ -7,8 +7,8 @@ py_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
requirement("tenacity"),
|
||||
"//idm/api/proto:idm_grpc_py",
|
||||
"//idm/api/proto:idm_proto_py",
|
||||
"//idm/api/proto:grpc_py",
|
||||
"//idm/api/proto:proto_py",
|
||||
requirement("aiogrpcclient"),
|
||||
],
|
||||
)
|
||||
|
@ -1,8 +1,6 @@
|
||||
from typing import Optional
|
||||
|
||||
from aiogrpcclient import BaseGrpcClient
|
||||
from grpc import StatusCode
|
||||
from grpc.experimental.aio import AioRpcError
|
||||
from idm.api.proto.chat_manager_service_pb2 import Chat as ChatPb
|
||||
from idm.api.proto.chat_manager_service_pb2 import Chats as ChatsPb
|
||||
from idm.api.proto.chat_manager_service_pb2 import (
|
||||
@ -12,12 +10,6 @@ from idm.api.proto.chat_manager_service_pb2 import (
|
||||
UpdateChatRequest,
|
||||
)
|
||||
from idm.api.proto.chat_manager_service_pb2_grpc import ChatManagerStub
|
||||
from tenacity import (
|
||||
retry,
|
||||
retry_if_exception,
|
||||
stop_after_attempt,
|
||||
wait_fixed,
|
||||
)
|
||||
|
||||
|
||||
class IdmApiGrpcClient(BaseGrpcClient):
|
||||
@ -44,14 +36,6 @@ class IdmApiGrpcClient(BaseGrpcClient):
|
||||
)
|
||||
return response
|
||||
|
||||
@retry(
|
||||
retry=retry_if_exception(
|
||||
lambda e: isinstance(e, AioRpcError) and e.code() == StatusCode.UNAVAILABLE
|
||||
),
|
||||
reraise=True,
|
||||
stop=stop_after_attempt(10),
|
||||
wait=wait_fixed(5),
|
||||
)
|
||||
async def get_chat(
|
||||
self,
|
||||
chat_id: int,
|
||||
|
@ -6,13 +6,5 @@ database:
|
||||
port: 5432
|
||||
grpc:
|
||||
address: 0.0.0.0
|
||||
port: 9090
|
||||
log_path: '/var/log/idm-api/{{ ENV_TYPE }}'
|
||||
telegram:
|
||||
# Telegram App Hash from https://my.telegram.org/
|
||||
app_hash: '{{ APP_HASH }}'
|
||||
# Telegram App ID from https://my.telegram.org/
|
||||
app_id: 00000
|
||||
database:
|
||||
session_id: '/usr/lib/idm-api/{{ ENV_TYPE }}/session.db'
|
||||
related_channel: '@nexus_search'
|
||||
port: 82
|
||||
log_path: '/var/log/idm-api'
|
||||
|
@ -13,10 +13,10 @@ logging:
|
||||
class: library.logging.formatters.TracebackFormatter
|
||||
handlers:
|
||||
debug:
|
||||
class: logging.StreamHandler
|
||||
class: library.logging.handlers.BaseFileHandler
|
||||
formatter: default
|
||||
filename: '{{ log_path }}/debug.log'
|
||||
level: DEBUG
|
||||
stream: 'ext://sys.stderr'
|
||||
error:
|
||||
class: library.logging.handlers.BaseFileHandler
|
||||
filename: '{{ log_path }}/error.log'
|
||||
|
@ -1,86 +0,0 @@
|
||||
import asyncio
|
||||
import logging
|
||||
import string
|
||||
|
||||
from aiokit import AioThing
|
||||
from library.telegram.base import BaseTelegramClient
|
||||
from telethon.tl.functions.channels import GetParticipantsRequest
|
||||
from telethon.tl.types import ChannelParticipantsSearch
|
||||
|
||||
|
||||
class AdminLogReader(AioThing):
|
||||
def __init__(self, telegram_config):
|
||||
super().__init__()
|
||||
self.subscriptors = set()
|
||||
self.loading = False
|
||||
self.telegram_client = BaseTelegramClient(
|
||||
app_id=telegram_config['app_id'],
|
||||
app_hash=telegram_config['app_hash'],
|
||||
database=telegram_config['database'],
|
||||
flood_sleep_threshold=25,
|
||||
)
|
||||
self.channel_name = telegram_config['related_channel']
|
||||
self.last_max_id = 0
|
||||
|
||||
def statbox(self, **kwargs):
|
||||
logging.getLogger('statbox').info({'mode': 'admin_log_reader', **kwargs})
|
||||
|
||||
async def skip_admin_log(self):
|
||||
async for event in self.telegram_client.iter_admin_log(self.channel_name, limit=1):
|
||||
self.last_max_id = event.id
|
||||
self.statbox(action='skipped_admin_log', max_id=self.last_max_id)
|
||||
|
||||
async def process_admin_log(self, sleep=1.0):
|
||||
self.loading = True
|
||||
try:
|
||||
while 1:
|
||||
async for event in self.telegram_client.iter_admin_log(
|
||||
self.channel_name, join=True, invite=True, leave=True, min_id=self.last_max_id
|
||||
):
|
||||
is_subscribed = event.joined or event.joined_invite
|
||||
if is_subscribed:
|
||||
self.subscriptors.add(event.user_id)
|
||||
elif event.user_id in self.subscriptors:
|
||||
self.subscriptors.remove(event.user_id)
|
||||
self.last_max_id = event.id
|
||||
await asyncio.sleep(sleep)
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
finally:
|
||||
self.loading = False
|
||||
|
||||
async def _fetch_users(self, query):
|
||||
max_batch_size = 200
|
||||
|
||||
participants = await self.telegram_client(
|
||||
GetParticipantsRequest(
|
||||
channel=self.channel_name,
|
||||
filter=ChannelParticipantsSearch(query),
|
||||
offset=0,
|
||||
limit=max_batch_size,
|
||||
hash=0,
|
||||
)
|
||||
)
|
||||
|
||||
for user in participants.users:
|
||||
self.subscriptors.add(user.id)
|
||||
|
||||
# There is a possibility that more users exist if we hit maximum count of users
|
||||
# So, we are making a recursion to reveal it
|
||||
if len(participants.users) == max_batch_size:
|
||||
for new_letter in string.ascii_lowercase + string.digits:
|
||||
await self._fetch_users(query + new_letter)
|
||||
|
||||
async def load_channel_users(self):
|
||||
self.statbox(action='load_channel_users')
|
||||
await self._fetch_users('')
|
||||
self.statbox(action='loaded_channel_users', subscriptors=len(self.subscriptors))
|
||||
|
||||
async def start(self):
|
||||
await self.telegram_client.start_and_wait()
|
||||
await self.skip_admin_log()
|
||||
await self.load_channel_users()
|
||||
asyncio.create_task(self.process_admin_log())
|
||||
|
||||
def is_subscribed(self, user_id):
|
||||
return not self.loading or user_id in self.subscriptors
|
@ -1,9 +1,7 @@
|
||||
import asyncio
|
||||
|
||||
import uvloop
|
||||
from aiopg.sa import create_engine
|
||||
from idm.api.configs import get_config
|
||||
from idm.api.daemons.admin_log_reader import AdminLogReader
|
||||
from idm.api.services.chat_manager import ChatManagerService
|
||||
from library.aiogrpctools import AioGrpcServer
|
||||
from library.aiopostgres.pool_holder import AioPostgresPoolHolder
|
||||
@ -14,27 +12,21 @@ from library.logging import configure_logging
|
||||
class GrpcServer(AioGrpcServer):
|
||||
def __init__(self, config: Configurator):
|
||||
super().__init__(address=config['grpc']['address'], port=config['grpc']['port'])
|
||||
database = config['database']
|
||||
self.pool_holder = AioPostgresPoolHolder(
|
||||
fn=create_engine,
|
||||
database=config['database']['database'],
|
||||
user=config['database']['username'],
|
||||
password=config['database']['password'],
|
||||
host=config['database']['host'],
|
||||
port=config['database']['port'],
|
||||
conninfo=f'dbname={database["database"]} '
|
||||
f'user={database["username"]} '
|
||||
f'password={database["password"]} '
|
||||
f'host={database["host"]}'
|
||||
f'port={database["port"]}',
|
||||
timeout=30,
|
||||
pool_recycle=60,
|
||||
maxsize=4,
|
||||
)
|
||||
self.admin_log_reader = AdminLogReader(
|
||||
telegram_config=config['telegram'],
|
||||
max_size=4,
|
||||
)
|
||||
self.chat_manager_service = ChatManagerService(
|
||||
server=self.server,
|
||||
service_name=config['application']['service_name'],
|
||||
pool_holder=self.pool_holder,
|
||||
admin_log_reader=self.admin_log_reader,
|
||||
)
|
||||
self.starts.append(self.admin_log_reader)
|
||||
self.waits.extend([self.chat_manager_service, self.pool_holder])
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@ load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
proto_library(
|
||||
name = "idm_proto",
|
||||
name = "proto",
|
||||
srcs = [
|
||||
"chat_manager_service.proto",
|
||||
],
|
||||
@ -14,12 +14,12 @@ proto_library(
|
||||
)
|
||||
|
||||
py_proto_library(
|
||||
name = "idm_proto_py",
|
||||
deps = [":idm_proto"],
|
||||
name = "proto_py",
|
||||
deps = [":proto"],
|
||||
)
|
||||
|
||||
py_grpc_library(
|
||||
name = "idm_grpc_py",
|
||||
srcs = [":idm_proto"],
|
||||
deps = [":idm_proto_py"],
|
||||
name = "grpc_py",
|
||||
srcs = [":proto"],
|
||||
deps = [":proto_py"],
|
||||
)
|
||||
|
@ -10,8 +10,8 @@ message Chat {
|
||||
int32 ban_until = 6;
|
||||
string ban_message = 7;
|
||||
bool is_admin = 8;
|
||||
bool is_subscribed = 9;
|
||||
int64 created_at = 10;
|
||||
int64 updated_at = 11;
|
||||
}
|
||||
|
||||
message Chats {
|
||||
|
@ -1,3 +1,5 @@
|
||||
import logging
|
||||
|
||||
from grpc import StatusCode
|
||||
from idm.api.proto.chat_manager_service_pb2 import Chat as ChatPb
|
||||
from idm.api.proto.chat_manager_service_pb2 import Chats as ChatsPb
|
||||
@ -5,6 +7,7 @@ from idm.api.proto.chat_manager_service_pb2_grpc import (
|
||||
ChatManagerServicer,
|
||||
add_ChatManagerServicer_to_server,
|
||||
)
|
||||
from izihawa_utils.pb_to_json import MessageToDict
|
||||
from library.aiogrpctools.base import (
|
||||
BaseService,
|
||||
aiogrpc_request_wrapper,
|
||||
@ -18,19 +21,14 @@ from pypika import (
|
||||
class ChatManagerService(ChatManagerServicer, BaseService):
|
||||
chats_table = Table('chats')
|
||||
|
||||
def __init__(self, server, service_name, pool_holder, admin_log_reader):
|
||||
def __init__(self, server, service_name, pool_holder):
|
||||
super().__init__(service_name=service_name)
|
||||
self.server = server
|
||||
self.pool_holder = pool_holder
|
||||
self.admin_log_reader = admin_log_reader
|
||||
|
||||
async def start(self):
|
||||
add_ChatManagerServicer_to_server(self, self.server)
|
||||
|
||||
def enrich_chat(self, chat_pb: ChatPb):
|
||||
chat_pb.is_subscribed = self.admin_log_reader.is_subscribed(chat_pb.chat_id)
|
||||
return chat_pb
|
||||
|
||||
@aiogrpc_request_wrapper()
|
||||
async def create_chat(self, request, context, metadata):
|
||||
chat = ChatPb(
|
||||
@ -75,7 +73,7 @@ class ChatManagerService(ChatManagerServicer, BaseService):
|
||||
chat = await result.fetchone()
|
||||
if chat is None:
|
||||
await context.abort(StatusCode.NOT_FOUND, 'not_found')
|
||||
return self.enrich_chat(ChatPb(**chat))
|
||||
return ChatPb(**chat)
|
||||
|
||||
@aiogrpc_request_wrapper()
|
||||
async def get_chat(self, request, context, metadata):
|
||||
@ -95,7 +93,7 @@ class ChatManagerService(ChatManagerServicer, BaseService):
|
||||
results = await session.execute(query)
|
||||
chats = await results.fetchall()
|
||||
return ChatsPb(
|
||||
chats=list(map(lambda x: self.enrich_chat(ChatPb(**x)), chats))
|
||||
chats=list(map(lambda x: ChatPb(**x), chats))
|
||||
)
|
||||
|
||||
@aiogrpc_request_wrapper()
|
||||
@ -109,4 +107,4 @@ class ChatManagerService(ChatManagerServicer, BaseService):
|
||||
async with self.pool_holder.pool.acquire() as session:
|
||||
result = await session.execute(query)
|
||||
chat = await result.fetchone()
|
||||
return self.enrich_chat(ChatPb(**chat))
|
||||
return ChatPb(**chat)
|
||||
|
@ -11,8 +11,8 @@ def images_install():
|
||||
|
||||
container_pull(
|
||||
name = "ubuntu",
|
||||
digest = "sha256:45ff0162921e61c004010a67db1bee7d039a677bed0cb294e61f2b47346d42b3",
|
||||
digest = "sha256:d0b4808a158b42b6efb3ae93abb567b1cb6ee097221813c0315390de0fa320b9",
|
||||
registry = "index.docker.io",
|
||||
repository = "library/ubuntu",
|
||||
tag = "20.10",
|
||||
tag = "21.10",
|
||||
)
|
||||
|
@ -26,6 +26,7 @@ class AioGrpcServer(AioRootThing):
|
||||
'address': self.address,
|
||||
'mode': 'grpc',
|
||||
'port': self.port,
|
||||
'extras': [x.__class__.__name__ for x in self.starts + self.waits]
|
||||
})
|
||||
await self.server.start()
|
||||
await self.server.wait_for_termination()
|
||||
@ -80,6 +81,8 @@ def aiogrpc_request_wrapper(log=True):
|
||||
return r
|
||||
except aio.AbortError:
|
||||
raise
|
||||
except aio.AioRpcError as e:
|
||||
await context.abort(e.code(), e.details())
|
||||
except Exception as e:
|
||||
serialized_request = MessageToDict(request, preserving_proto_field_name=True)
|
||||
error_log(e, request=serialized_request, request_id=metadata.get('request-id'))
|
||||
@ -107,8 +110,8 @@ def aiogrpc_streaming_request_wrapper(func):
|
||||
mode=func.__name__,
|
||||
request_id=metadata.get('request-id'),
|
||||
)
|
||||
except aio.AbortError:
|
||||
raise
|
||||
except aio.AioRpcError as e:
|
||||
await context.abort(e.code(), e.details())
|
||||
except Exception as e:
|
||||
serialized_request = MessageToDict(request, preserving_proto_field_name=True)
|
||||
error_log(e, request=serialized_request, request_id=metadata.get('request-id'))
|
||||
|
@ -10,7 +10,9 @@ py_library(
|
||||
srcs_version = "PY3",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
requirement("aiopg"),
|
||||
requirement("psycopg"),
|
||||
requirement("psycopg-pool"),
|
||||
requirement("psycopg-binary"),
|
||||
requirement("tenacity"),
|
||||
requirement("aiokit"),
|
||||
],
|
||||
|
@ -1,42 +1,51 @@
|
||||
import aiopg
|
||||
import psycopg2.extras
|
||||
from typing import Optional
|
||||
|
||||
from aiokit import AioThing
|
||||
from psycopg2 import OperationalError
|
||||
from tenacity import (
|
||||
retry,
|
||||
retry_if_exception_type,
|
||||
stop_after_attempt,
|
||||
wait_fixed,
|
||||
)
|
||||
from psycopg.rows import tuple_row
|
||||
from psycopg_pool import AsyncConnectionPool
|
||||
|
||||
|
||||
class AioPostgresPoolHolder(AioThing):
|
||||
def __init__(self, fn=aiopg.create_pool, *args, **kwargs):
|
||||
def __init__(self, conninfo, timeout=30, min_size=1, max_size=4):
|
||||
super().__init__()
|
||||
self.fn = fn
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.pool = None
|
||||
|
||||
@retry(
|
||||
retry=retry_if_exception_type(OperationalError),
|
||||
stop=stop_after_attempt(3),
|
||||
wait=wait_fixed(1.0),
|
||||
self.fn = lambda: AsyncConnectionPool(
|
||||
conninfo=conninfo,
|
||||
timeout=timeout,
|
||||
min_size=min_size,
|
||||
max_size=max_size,
|
||||
)
|
||||
|
||||
async def start(self):
|
||||
if not self.pool:
|
||||
self.pool = await self.fn(*self.args, **self.kwargs)
|
||||
self.pool = self.fn()
|
||||
|
||||
async def stop(self):
|
||||
if self.pool:
|
||||
self.pool.close()
|
||||
await self.pool.wait_closed()
|
||||
await self.pool.close()
|
||||
self.pool = None
|
||||
|
||||
async def execute(self, stmt, values=None, fetch=False, timeout=None, cursor_factory=psycopg2.extras.DictCursor):
|
||||
async with self.pool.acquire() as conn:
|
||||
async with conn.cursor(cursor_factory=cursor_factory) as cur:
|
||||
await cur.execute(stmt, values, timeout=timeout)
|
||||
if fetch:
|
||||
return await cur.fetchall()
|
||||
return cur.rowcount
|
||||
async def iterate(
|
||||
self,
|
||||
stmt: str,
|
||||
values=None,
|
||||
row_factory=tuple_row,
|
||||
cursor_name: Optional[str] = None,
|
||||
itersize: Optional[int] = None,
|
||||
):
|
||||
if not self.pool:
|
||||
raise RuntimeError('AioPostgresPoolHolder has not been started')
|
||||
async with self.pool.connection() as conn:
|
||||
async with conn.cursor(name=cursor_name, row_factory=row_factory) as cur:
|
||||
if itersize is not None:
|
||||
cur.itersize = itersize
|
||||
await cur.execute(stmt, values)
|
||||
async for row in cur:
|
||||
yield row
|
||||
|
||||
async def execute(self, stmt: str, values=None, cursor_name: Optional[str] = None, row_factory=tuple_row):
|
||||
if not self.pool:
|
||||
raise RuntimeError('AioPostgresPoolHolder has not been started')
|
||||
async with self.pool.connection() as conn:
|
||||
async with conn.cursor(name=cursor_name, row_factory=row_factory) as cur:
|
||||
await cur.execute(stmt, values)
|
||||
|
@ -86,8 +86,14 @@ class Configurator(RichDict):
|
||||
elif isinstance(c, list):
|
||||
return [self.walk_and_render(e) for e in c]
|
||||
elif isinstance(c, dict):
|
||||
for key in c:
|
||||
for key in list(c.keys()):
|
||||
c[key] = self.walk_and_render(c[key])
|
||||
if key.endswith('_filepath'):
|
||||
with open(c[key]) as f:
|
||||
if c[key].endswith('.json'):
|
||||
c[key.replace('_filepath', '')] = json.loads(f.read())
|
||||
elif c[key].endswith('.yaml'):
|
||||
c[key.replace('_filepath', '')] = yaml.safe_load(f.read())
|
||||
return c
|
||||
|
||||
def update(self, new_config, basename=None, **kwargs):
|
||||
|
@ -1,12 +1,14 @@
|
||||
import asyncio
|
||||
import datetime
|
||||
import logging
|
||||
import os.path
|
||||
from typing import (
|
||||
Optional,
|
||||
Union,
|
||||
)
|
||||
|
||||
from aiokit import AioThing
|
||||
from izihawa_utils.random import random_string
|
||||
from izihawa_utils.random import generate_request_id
|
||||
from library.logging import error_log
|
||||
from telethon import (
|
||||
TelegramClient,
|
||||
@ -16,6 +18,7 @@ from telethon import (
|
||||
from tenacity import ( # noqa
|
||||
retry,
|
||||
retry_if_exception_type,
|
||||
stop_after_attempt,
|
||||
wait_fixed,
|
||||
)
|
||||
|
||||
@ -28,6 +31,8 @@ class BaseTelegramClient(AioThing):
|
||||
app_id: Union[int, str],
|
||||
app_hash: str,
|
||||
database: dict,
|
||||
phone: Optional[str] = None,
|
||||
password: Optional[str] = None,
|
||||
bot_token: Optional[str] = None,
|
||||
mtproxy: Optional[dict] = None,
|
||||
flood_sleep_threshold: int = 60,
|
||||
@ -44,6 +49,8 @@ class BaseTelegramClient(AioThing):
|
||||
flood_sleep_threshold=flood_sleep_threshold,
|
||||
**self._get_proxy(mtproxy=mtproxy),
|
||||
)
|
||||
self.phone = phone
|
||||
self.password = password
|
||||
self.bot_token = bot_token
|
||||
|
||||
def _get_session(self, database):
|
||||
@ -71,9 +78,23 @@ class BaseTelegramClient(AioThing):
|
||||
}
|
||||
return {}
|
||||
|
||||
@retry(retry=retry_if_exception_type(ConnectionError), wait=wait_fixed(5))
|
||||
@retry(retry=retry_if_exception_type(ConnectionError), stop=stop_after_attempt(3), wait=wait_fixed(5))
|
||||
async def start(self):
|
||||
await self._telegram_client.start(bot_token=self.bot_token)
|
||||
logging.getLogger('debug').info({'mode': 'telegram', 'action': 'starting'})
|
||||
await self._telegram_client.start(
|
||||
phone=lambda: self.phone,
|
||||
bot_token=self.bot_token,
|
||||
password=self.password,
|
||||
code_callback=self.polling_file,
|
||||
)
|
||||
logging.getLogger('debug').info({'mode': 'telegram', 'action': 'started'})
|
||||
|
||||
async def polling_file(self):
|
||||
fname = '/tmp/telegram_code'
|
||||
while not os.path.exists(fname):
|
||||
await asyncio.sleep(5.0)
|
||||
with open(fname, 'r') as code_file:
|
||||
return code_file.read().strip()
|
||||
|
||||
async def stop(self):
|
||||
return await self.disconnect()
|
||||
@ -119,6 +140,9 @@ class BaseTelegramClient(AioThing):
|
||||
def get_input_entity(self, *args, **kwargs):
|
||||
return self._telegram_client.get_input_entity(*args, **kwargs)
|
||||
|
||||
def get_permissions(self, *args, **kwargs):
|
||||
return self._telegram_client.get_permissions(*args, **kwargs)
|
||||
|
||||
def iter_admin_log(self, *args, **kwargs):
|
||||
return self._telegram_client.iter_admin_log(*args, **kwargs)
|
||||
|
||||
@ -158,7 +182,7 @@ class RequestContext:
|
||||
|
||||
@staticmethod
|
||||
def generate_request_id(length):
|
||||
return random_string(length)
|
||||
return generate_request_id(length)
|
||||
|
||||
def add_default_fields(self, **fields):
|
||||
self.default_fields.update(fields)
|
||||
|
@ -18,8 +18,8 @@ py_library(
|
||||
requirement("aiocrossref"),
|
||||
requirement("aiolibgen"),
|
||||
"//library/aiopostgres",
|
||||
"//nexus/models/proto:models_proto_py",
|
||||
requirement("izihawa_types"),
|
||||
"//nexus/models/proto:proto_py",
|
||||
"//nexus/nlptools",
|
||||
requirement("aiosumma"),
|
||||
],
|
||||
)
|
||||
|
@ -1,27 +0,0 @@
|
||||
from .update_document import SendDocumentOperationUpdateDocumentPbToSummaAction
|
||||
from .update_document_scimag import (
|
||||
CleanDocumentOperationUpdateDocumentScimagPbAction,
|
||||
FillDocumentOperationUpdateDocumentScimagPbFromExternalSourceAction,
|
||||
SendDocumentOperationUpdateDocumentScimagPbReferencesToKafkaAction,
|
||||
SendDocumentOperationUpdateDocumentScimagPbToGoldenPostgresAction,
|
||||
)
|
||||
from .update_document_scitech import (
|
||||
CleanDocumentOperationUpdateDocumentScitechPbAction,
|
||||
SendDocumentOperationUpdateDocumentScitechPbToGoldenPostgresAction,
|
||||
)
|
||||
from .update_document_sharience import (
|
||||
SendDocumentOperationUpdateDocumentShariencePbToGoldenPostgresAction,
|
||||
)
|
||||
from .vote import SendDocumentOperationVotePbToGoldenPostgresAction
|
||||
|
||||
__all__ = [
|
||||
'CleanDocumentOperationUpdateDocumentScimagPbAction',
|
||||
'CleanDocumentOperationUpdateDocumentScitechPbAction',
|
||||
'FillDocumentOperationUpdateDocumentScimagPbFromExternalSourceAction',
|
||||
'SendDocumentOperationUpdateDocumentPbToSummaAction',
|
||||
'SendDocumentOperationUpdateDocumentScimagPbReferencesToKafkaAction',
|
||||
'SendDocumentOperationUpdateDocumentScimagPbToGoldenPostgresAction',
|
||||
'SendDocumentOperationUpdateDocumentScitechPbToGoldenPostgresAction',
|
||||
'SendDocumentOperationUpdateDocumentShariencePbToGoldenPostgresAction',
|
||||
'SendDocumentOperationVotePbToGoldenPostgresAction',
|
||||
]
|
@ -2,4 +2,12 @@ from urllib.parse import unquote
|
||||
|
||||
|
||||
def canonize_doi(doi):
|
||||
return unquote(doi.lower())
|
||||
return (
|
||||
unquote(doi.lower())
|
||||
.replace('\\n', '\n')
|
||||
.replace('\n', '')
|
||||
.replace('\\', '')
|
||||
.strip('\'"')
|
||||
.replace('\x00', '')
|
||||
.strip()
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ from datetime import date
|
||||
from nexus.models.proto.scimag_pb2 import Scimag as ScimagPb
|
||||
|
||||
from .base import BaseAction
|
||||
from .exceptions import InterruptProcessing
|
||||
|
||||
|
||||
def extract_authors(authors):
|
||||
@ -17,7 +18,7 @@ def extract_authors(authors):
|
||||
|
||||
def extract_dates(date_parts):
|
||||
if not date_parts or not date_parts[0]:
|
||||
return '', None
|
||||
return 0, None
|
||||
year, month, day = date_parts[0] + [0] * (3 - len(date_parts[0]))
|
||||
if year:
|
||||
issued_at = int(time.mktime(date(
|
||||
@ -25,8 +26,8 @@ def extract_dates(date_parts):
|
||||
month=month if month else 1,
|
||||
day=day if day else 1,
|
||||
).timetuple()))
|
||||
return str(year), issued_at
|
||||
return '', None
|
||||
return year, issued_at
|
||||
return 0, None
|
||||
|
||||
|
||||
def extract_first(arr, default=''):
|
||||
@ -74,13 +75,17 @@ def extract_title(title, subtitle):
|
||||
return ': '.join(filter(lambda x: bool(x), [title.strip(), subtitle.strip()]))
|
||||
|
||||
|
||||
class CrossrefApiToThinScimagPbAction(BaseAction):
|
||||
class ToThinScimagPbAction(BaseAction):
|
||||
async def do(self, item: dict) -> ScimagPb:
|
||||
if 'DOI' not in item:
|
||||
raise InterruptProcessing(document_id=None, reason='no_doi')
|
||||
return ScimagPb(doi=item['DOI'])
|
||||
|
||||
|
||||
class CrossrefApiToScimagPbAction(BaseAction):
|
||||
class ToScimagPbAction(BaseAction):
|
||||
async def do(self, item: dict) -> ScimagPb:
|
||||
if 'DOI' not in item:
|
||||
raise InterruptProcessing(document_id=None, reason='no_doi')
|
||||
scimag_pb = ScimagPb(
|
||||
abstract=item.get('abstract'),
|
||||
container_title=extract_first(item.get('container-title')),
|
||||
|
@ -0,0 +1,41 @@
|
||||
from library.aiopostgres.pool_holder import AioPostgresPoolHolder
|
||||
from nexus.models.proto.operation_pb2 import \
|
||||
DocumentOperation as DocumentOperationPb
|
||||
from pypika import (
|
||||
PostgreSQLQuery,
|
||||
Table,
|
||||
)
|
||||
|
||||
from ..base import BaseAction
|
||||
|
||||
|
||||
class ToPostgresAction(BaseAction):
|
||||
telegram_files_table = Table('telegram_files')
|
||||
|
||||
def __init__(self, database):
|
||||
super().__init__()
|
||||
self.pool_holder = AioPostgresPoolHolder(
|
||||
conninfo=f'dbname={database["database"]} '
|
||||
f'user={database["username"]} '
|
||||
f'password={database["password"]} '
|
||||
f'host={database["host"]}',
|
||||
)
|
||||
self.waits.append(self.pool_holder)
|
||||
|
||||
async def do(self, document_operation_pb: DocumentOperationPb) -> DocumentOperationPb:
|
||||
store_telegram_file_id_pb = document_operation_pb.store_telegram_file_id
|
||||
|
||||
query = (
|
||||
PostgreSQLQuery
|
||||
.into(self.telegram_files_table)
|
||||
.columns('bot_name', 'document_id', 'telegram_file_id')
|
||||
.insert(
|
||||
store_telegram_file_id_pb.bot_name,
|
||||
store_telegram_file_id_pb.document_id,
|
||||
store_telegram_file_id_pb.telegram_file_id,
|
||||
)
|
||||
.on_conflict('bot_name', 'document_id')
|
||||
.do_nothing()
|
||||
)
|
||||
await self.pool_holder.execute(query.get_sql())
|
||||
return document_operation_pb
|
@ -4,7 +4,6 @@ from typing import (
|
||||
Set,
|
||||
)
|
||||
|
||||
import aiopg
|
||||
from aiocrossref import CrossrefClient
|
||||
from aiocrossref.exceptions import (
|
||||
NotFoundError,
|
||||
@ -23,13 +22,13 @@ from pypika import (
|
||||
)
|
||||
from pypika.terms import Array
|
||||
|
||||
from .base import BaseAction
|
||||
from .crossref_api import CrossrefApiToScimagPbAction
|
||||
from .exceptions import InterruptProcessing
|
||||
from .scimag import CleanScimagPbAction
|
||||
from .. import scimag_pb
|
||||
from ..base import BaseAction
|
||||
from ..crossref_api import ToScimagPbAction
|
||||
from ..exceptions import InterruptProcessing
|
||||
|
||||
|
||||
class SendDocumentOperationUpdateDocumentScimagPbToGoldenPostgresAction(BaseAction):
|
||||
class ToPostgresAction(BaseAction):
|
||||
scimag_table = Table('scimag')
|
||||
db_multi_fields = {
|
||||
'authors',
|
||||
@ -55,7 +54,6 @@ class SendDocumentOperationUpdateDocumentScimagPbToGoldenPostgresAction(BaseActi
|
||||
'md5',
|
||||
'ref_by_count',
|
||||
'scimag_bulk_id',
|
||||
'telegram_file_id',
|
||||
'title',
|
||||
'type',
|
||||
'updated_at',
|
||||
@ -66,14 +64,10 @@ class SendDocumentOperationUpdateDocumentScimagPbToGoldenPostgresAction(BaseActi
|
||||
def __init__(self, database):
|
||||
super().__init__()
|
||||
self.pool_holder = AioPostgresPoolHolder(
|
||||
fn=aiopg.create_pool,
|
||||
dsn=f'dbname={database["database"]} '
|
||||
conninfo=f'dbname={database["database"]} '
|
||||
f'user={database["username"]} '
|
||||
f'password={database["password"]} '
|
||||
f'host={database["host"]}',
|
||||
timeout=30,
|
||||
pool_recycle=60,
|
||||
maxsize=4,
|
||||
)
|
||||
self.waits.append(self.pool_holder)
|
||||
|
||||
@ -153,12 +147,12 @@ class SendDocumentOperationUpdateDocumentScimagPbToGoldenPostgresAction(BaseActi
|
||||
scimag_pb=scimag_pb,
|
||||
fields=fields,
|
||||
)
|
||||
result = await self.pool_holder.execute(sql, fetch=True)
|
||||
result = [row async for row in self.pool_holder.iterate(sql)]
|
||||
scimag_pb.id = result[0][0]
|
||||
return document_operation_pb
|
||||
|
||||
|
||||
class SendDocumentOperationUpdateDocumentScimagPbReferencesToKafkaAction(BaseAction):
|
||||
class ReferencesToKafkaAction(BaseAction):
|
||||
def __init__(self, topic, brokers):
|
||||
super().__init__()
|
||||
self.topic = topic
|
||||
@ -194,7 +188,7 @@ class SendDocumentOperationUpdateDocumentScimagPbReferencesToKafkaAction(BaseAct
|
||||
return document_operation_pb
|
||||
|
||||
|
||||
class FillDocumentOperationUpdateDocumentScimagPbFromExternalSourceAction(BaseAction):
|
||||
class FillFromExternalSourceAction(BaseAction):
|
||||
def __init__(self, crossref):
|
||||
super().__init__()
|
||||
self.crossref_client = CrossrefClient(
|
||||
@ -204,8 +198,9 @@ class FillDocumentOperationUpdateDocumentScimagPbFromExternalSourceAction(BaseAc
|
||||
retry_delay=crossref.get('retry_delay', 0.5),
|
||||
timeout=crossref.get('timeout'),
|
||||
user_agent=crossref.get('user_agent'),
|
||||
ttl_dns_cache=crossref.get('ttl_dns_cache'),
|
||||
)
|
||||
self.crossref_api_to_scimag_pb_action = CrossrefApiToScimagPbAction()
|
||||
self.crossref_api_to_scimag_pb_action = ToScimagPbAction()
|
||||
self.waits.append(self.crossref_client)
|
||||
|
||||
async def do(self, document_operation_pb: DocumentOperationPb) -> DocumentOperationPb:
|
||||
@ -216,16 +211,16 @@ class FillDocumentOperationUpdateDocumentScimagPbFromExternalSourceAction(BaseAc
|
||||
try:
|
||||
crossref_api_response = await self.crossref_client.works(doi=scimag_pb.doi)
|
||||
except (WrongContentTypeError, NotFoundError) as e:
|
||||
raise InterruptProcessing(doc_id=scimag_pb.doi, reason=str(e))
|
||||
raise InterruptProcessing(document_id=scimag_pb.doi, reason=str(e))
|
||||
new_scimag_pb = await self.crossref_api_to_scimag_pb_action.do(crossref_api_response)
|
||||
scimag_pb.MergeFrom(new_scimag_pb)
|
||||
return document_operation_pb
|
||||
|
||||
|
||||
class CleanDocumentOperationUpdateDocumentScimagPbAction(BaseAction):
|
||||
class CleanAction(BaseAction):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.cleaner = CleanScimagPbAction()
|
||||
self.cleaner = scimag_pb.CleanAction()
|
||||
self.waits.append(self.cleaner)
|
||||
|
||||
async def do(self, document_operation_pb: DocumentOperationPb) -> DocumentOperationPb:
|
@ -1,4 +1,6 @@
|
||||
import aiopg
|
||||
import logging
|
||||
|
||||
from izihawa_utils.pb_to_json import MessageToDict
|
||||
from library.aiopostgres.pool_holder import AioPostgresPoolHolder
|
||||
from nexus.models.proto.operation_pb2 import \
|
||||
DocumentOperation as DocumentOperationPb
|
||||
@ -10,17 +12,17 @@ from pypika import (
|
||||
)
|
||||
from pypika.terms import Array
|
||||
|
||||
from .base import BaseAction
|
||||
from .exceptions import ConflictError
|
||||
from .scitech import CleanScitechAction
|
||||
from .. import scitech_pb
|
||||
from ..base import BaseAction
|
||||
from ..exceptions import ConflictError
|
||||
|
||||
|
||||
class UuidFunction(functions.Function):
|
||||
def __init__(self, uuid, alias=None):
|
||||
super(UuidFunction, self).__init__('UUID', uuid, alias=alias)
|
||||
def __init__(self, uuid, name=None):
|
||||
super(UuidFunction, self).__init__('UUID', uuid, name=name)
|
||||
|
||||
|
||||
class SendDocumentOperationUpdateDocumentScitechPbToGoldenPostgresAction(BaseAction):
|
||||
class ToPostgresAction(BaseAction):
|
||||
scitech_table = Table('scitech')
|
||||
db_single_fields = {
|
||||
'id',
|
||||
@ -41,7 +43,6 @@ class SendDocumentOperationUpdateDocumentScitechPbToGoldenPostgresAction(BaseAct
|
||||
'original_id',
|
||||
'pages',
|
||||
'series',
|
||||
'telegram_file_id',
|
||||
'title',
|
||||
'updated_at',
|
||||
'volume',
|
||||
@ -57,25 +58,23 @@ class SendDocumentOperationUpdateDocumentScitechPbToGoldenPostgresAction(BaseAct
|
||||
def __init__(self, database):
|
||||
super().__init__()
|
||||
self.pool_holder = AioPostgresPoolHolder(
|
||||
fn=aiopg.create_pool,
|
||||
dsn=f'dbname={database["database"]} '
|
||||
conninfo=f'dbname={database["database"]} '
|
||||
f'user={database["username"]} '
|
||||
f'password={database["password"]} '
|
||||
f'host={database["host"]}',
|
||||
timeout=30,
|
||||
pool_recycle=60,
|
||||
maxsize=4,
|
||||
)
|
||||
self.waits.append(self.pool_holder)
|
||||
|
||||
def cast_field_value(self, field_name, field_value):
|
||||
if field_name in self.db_multi_fields:
|
||||
field_value = Array(*field_value)
|
||||
if field_name in {'title', }:
|
||||
field_value = field_value.replace('\0', '').strip()
|
||||
return field_name, field_value
|
||||
|
||||
def is_field_set(self, scitech_pb: ScitechPb, field_name: str):
|
||||
field_value = getattr(scitech_pb, field_name)
|
||||
if field_name in {'issued_at'}:
|
||||
if field_name in {'issued_at', }:
|
||||
return scitech_pb.HasField(field_name)
|
||||
return field_value
|
||||
|
||||
@ -107,10 +106,7 @@ class SendDocumentOperationUpdateDocumentScitechPbToGoldenPostgresAction(BaseAct
|
||||
.where(casted_conditions)
|
||||
.get_sql()
|
||||
)
|
||||
result = await self.pool_holder.execute(
|
||||
sql,
|
||||
fetch=True
|
||||
)
|
||||
result = [row async for row in self.pool_holder.iterate(sql)]
|
||||
count = result[0][0]
|
||||
|
||||
if count > 1:
|
||||
@ -144,15 +140,19 @@ class SendDocumentOperationUpdateDocumentScitechPbToGoldenPostgresAction(BaseAct
|
||||
query = query.do_update(col, val)
|
||||
sql = query.returning('id', 'original_id').get_sql()
|
||||
|
||||
result = await self.pool_holder.execute(sql, fetch=True)
|
||||
try:
|
||||
result = [row async for row in self.pool_holder.iterate(sql)]
|
||||
except:
|
||||
logging.getLogger('error').error({'sql': sql, 'scitech': MessageToDict(scitech_pb)})
|
||||
raise
|
||||
scitech_pb.id, scitech_pb.original_id = result[0][0], result[0][1] or 0
|
||||
return document_operation_pb
|
||||
|
||||
|
||||
class CleanDocumentOperationUpdateDocumentScitechPbAction(BaseAction):
|
||||
class CleanAction(BaseAction):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.cleaner = CleanScitechAction()
|
||||
self.cleaner = scitech_pb.CleanAction()
|
||||
self.waits.append(self.cleaner)
|
||||
|
||||
async def do(self, document_operation_pb: DocumentOperationPb) -> DocumentOperationPb:
|
@ -3,7 +3,6 @@ from typing import (
|
||||
Set,
|
||||
)
|
||||
|
||||
import aiopg
|
||||
from library.aiopostgres.pool_holder import AioPostgresPoolHolder
|
||||
from nexus.models.proto.operation_pb2 import \
|
||||
DocumentOperation as DocumentOperationPb
|
||||
@ -14,10 +13,10 @@ from pypika import (
|
||||
)
|
||||
from pypika.terms import Array
|
||||
|
||||
from .base import BaseAction
|
||||
from ..base import BaseAction
|
||||
|
||||
|
||||
class SendDocumentOperationUpdateDocumentShariencePbToGoldenPostgresAction(BaseAction):
|
||||
class ToPostgresAction(BaseAction):
|
||||
sharience_table = Table('sharience')
|
||||
db_multi_fields = {
|
||||
'ipfs_multihashes',
|
||||
@ -28,7 +27,6 @@ class SendDocumentOperationUpdateDocumentShariencePbToGoldenPostgresAction(BaseA
|
||||
'uploader_id',
|
||||
'filesize',
|
||||
'md5',
|
||||
'telegram_file_id',
|
||||
'updated_at',
|
||||
}
|
||||
db_fields = db_single_fields | db_multi_fields
|
||||
@ -36,14 +34,10 @@ class SendDocumentOperationUpdateDocumentShariencePbToGoldenPostgresAction(BaseA
|
||||
def __init__(self, database):
|
||||
super().__init__()
|
||||
self.pool_holder = AioPostgresPoolHolder(
|
||||
fn=aiopg.create_pool,
|
||||
dsn=f'dbname={database["database"]} '
|
||||
conninfo=f'dbname={database["database"]} '
|
||||
f'user={database["username"]} '
|
||||
f'password={database["password"]} '
|
||||
f'host={database["host"]}',
|
||||
timeout=30,
|
||||
pool_recycle=60,
|
||||
maxsize=4,
|
||||
)
|
||||
self.waits.append(self.pool_holder)
|
||||
|
||||
@ -80,7 +74,7 @@ class SendDocumentOperationUpdateDocumentShariencePbToGoldenPostgresAction(BaseA
|
||||
sharience_pb=sharience_pb,
|
||||
fields=fields,
|
||||
)
|
||||
result = await self.pool_holder.execute(sql, fetch=True)
|
||||
result = [row async for row in self.pool_holder.iterate(sql)]
|
||||
sharience_pb.id = result[0][0]
|
||||
|
||||
return document_operation_pb
|
@ -1,4 +1,3 @@
|
||||
import aiopg
|
||||
from library.aiopostgres.pool_holder import AioPostgresPoolHolder
|
||||
from nexus.models.proto.operation_pb2 import \
|
||||
DocumentOperation as DocumentOperationPb
|
||||
@ -7,23 +6,20 @@ from pypika import (
|
||||
Table,
|
||||
)
|
||||
|
||||
from .base import BaseAction
|
||||
from ..base import BaseAction
|
||||
|
||||
|
||||
class SendDocumentOperationVotePbToGoldenPostgresAction(BaseAction):
|
||||
class ToPostgresAction(BaseAction):
|
||||
votes_table = Table('votes')
|
||||
|
||||
def __init__(self, database):
|
||||
super().__init__()
|
||||
self.pool_holder = AioPostgresPoolHolder(
|
||||
fn=aiopg.create_pool,
|
||||
dsn=f'dbname={database["database"]} '
|
||||
conninfo=f'dbname={database["database"]} '
|
||||
f'user={database["username"]} '
|
||||
f'password={database["password"]} '
|
||||
f'host={database["host"]}',
|
||||
timeout=30,
|
||||
pool_recycle=60,
|
||||
maxsize=2,
|
||||
max_size=2,
|
||||
)
|
||||
self.waits.append(self.pool_holder)
|
||||
|
@ -6,8 +6,8 @@ from izihawa_utils.exceptions import BaseError
|
||||
class InterruptProcessing(BaseError):
|
||||
code = 'interrupt_processing'
|
||||
|
||||
def __init__(self, doc_id, reason):
|
||||
super().__init__(doc_id=doc_id, reason=reason)
|
||||
def __init__(self, document_id, reason):
|
||||
super().__init__(document_id=document_id, reason=reason)
|
||||
|
||||
|
||||
class ConflictError(BaseError):
|
||||
|
@ -1,8 +0,0 @@
|
||||
from nexus.models.proto.scimag_pb2 import Scimag as ScimagPb
|
||||
|
||||
from .base import BaseAction
|
||||
|
||||
|
||||
class GoldenPostgresToThinScimagPbAction(BaseAction):
|
||||
async def do(self, item: dict) -> ScimagPb:
|
||||
return ScimagPb(doi=item['doi'])
|
@ -84,7 +84,7 @@ def create_cu(libgen_id, coverurl, md5):
|
||||
return coverurl, cu_suf
|
||||
|
||||
|
||||
class LibgenApiToScitechPbAction(BaseAction):
|
||||
class ToScitechPbAction(BaseAction):
|
||||
async def do(self, item: dict) -> ScitechPb:
|
||||
scitech_pb = ScitechPb(
|
||||
authors=(item.get('author') or '').split('; '),
|
||||
@ -113,7 +113,7 @@ class LibgenApiToScitechPbAction(BaseAction):
|
||||
item['tags'].split(';')
|
||||
),
|
||||
)),
|
||||
title=item['title'],
|
||||
title=item['title'].replace('\0', '').strip(),
|
||||
)
|
||||
|
||||
scitech_pb.cu, scitech_pb.cu_suf = create_cu(
|
||||
@ -123,6 +123,7 @@ class LibgenApiToScitechPbAction(BaseAction):
|
||||
)
|
||||
year = safe_int(item['year'])
|
||||
if year and year < 9999:
|
||||
scitech_pb.year = str(year)
|
||||
scitech_pb.issued_at = np.datetime64(scitech_pb.year).astype('<M8[s]').astype(np.int64)
|
||||
scitech_pb.year = year
|
||||
# Subtract 1970
|
||||
scitech_pb.issued_at = np.datetime64(year, 'Y').astype('datetime64[s]').astype(np.int64) - 62167132800
|
||||
return scitech_pb
|
||||
|
34
nexus/actions/postgres.py
Normal file
@ -0,0 +1,34 @@
|
||||
import orjson as json
|
||||
from izihawa_utils.common import filter_none
|
||||
from nexus.models.proto.scimag_pb2 import Scimag as ScimagPb
|
||||
from summa.proto.proto_grpc_py_pb import index_pb2 as index_pb
|
||||
|
||||
from .base import BaseAction
|
||||
|
||||
|
||||
class ToThinScimagPbAction(BaseAction):
|
||||
async def do(self, item: dict) -> ScimagPb:
|
||||
return ScimagPb(doi=item['doi'])
|
||||
|
||||
|
||||
class ScitechToIndexOperationBytesAction(BaseAction):
|
||||
restricted_column_set = [
|
||||
'extension',
|
||||
'fiction_id',
|
||||
'filesize',
|
||||
'has_duplicates',
|
||||
'ipfs_multihashes',
|
||||
'libgen_id',
|
||||
'md5',
|
||||
'original_id',
|
||||
]
|
||||
|
||||
async def do(self, item: dict) -> bytes:
|
||||
# if item['original_id'] is not None:
|
||||
# item = {rc: item[rc] for rc in self.restricted_column_set}
|
||||
return index_pb.IndexOperation(
|
||||
index_document=index_pb.IndexDocumentOperation(
|
||||
document=json.dumps(filter_none(item)),
|
||||
reindex=True,
|
||||
),
|
||||
).SerializeToString()
|
@ -1,7 +1,6 @@
|
||||
from html import unescape
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from nexus.actions.common import canonize_doi
|
||||
from nexus.models.proto.operation_pb2 import \
|
||||
DocumentOperation as DocumentOperationPb
|
||||
from nexus.models.proto.operation_pb2 import UpdateDocument as UpdateDocumentPb
|
||||
@ -15,9 +14,10 @@ from nexus.nlptools.utils import (
|
||||
)
|
||||
|
||||
from .base import BaseAction
|
||||
from .common import canonize_doi
|
||||
|
||||
|
||||
class CleanScimagPbAction(BaseAction):
|
||||
class CleanAction(BaseAction):
|
||||
async def do(self, scimag_pb: ScimagPb) -> ScimagPb:
|
||||
if scimag_pb.abstract:
|
||||
abstract_soup = BeautifulSoup(unescape(scimag_pb.abstract), 'lxml')
|
||||
@ -61,7 +61,7 @@ class CleanScimagPbAction(BaseAction):
|
||||
return scimag_pb
|
||||
|
||||
|
||||
class ScimagPbToDocumentOperationBytesAction(BaseAction):
|
||||
class ToDocumentOperationAction(BaseAction):
|
||||
async def do(self, item: ScimagPb) -> bytes:
|
||||
document_operation_pb = DocumentOperationPb(
|
||||
update_document=UpdateDocumentPb(
|
@ -1,7 +1,6 @@
|
||||
from html import unescape
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from nexus.actions.common import canonize_doi
|
||||
from nexus.models.proto.operation_pb2 import \
|
||||
DocumentOperation as DocumentOperationPb
|
||||
from nexus.models.proto.operation_pb2 import UpdateDocument as UpdateDocumentPb
|
||||
@ -15,9 +14,10 @@ from nexus.nlptools.utils import (
|
||||
)
|
||||
|
||||
from .base import BaseAction
|
||||
from .common import canonize_doi
|
||||
|
||||
|
||||
class CleanScitechAction(BaseAction):
|
||||
class CleanAction(BaseAction):
|
||||
async def do(self, scitech_pb: ScitechPb) -> ScitechPb:
|
||||
if scitech_pb.authors:
|
||||
for i, author in enumerate(scitech_pb.authors):
|
||||
@ -47,7 +47,7 @@ class CleanScitechAction(BaseAction):
|
||||
return scitech_pb
|
||||
|
||||
|
||||
class ScitechPbToDocumentOperationBytesAction(BaseAction):
|
||||
class ToDocumentOperationPbAction(BaseAction):
|
||||
async def do(self, item: ScitechPb) -> bytes:
|
||||
document_operation_pb = DocumentOperationPb(
|
||||
update_document=UpdateDocumentPb(
|
@ -1,31 +0,0 @@
|
||||
from aiosumma import SummaHttpClient
|
||||
from izihawa_utils.pb_to_json import MessageToDict
|
||||
from nexus.models.proto.operation_pb2 import \
|
||||
DocumentOperation as DocumentOperationPb
|
||||
|
||||
from .base import BaseAction
|
||||
|
||||
|
||||
class SendDocumentOperationUpdateDocumentPbToSummaAction(BaseAction):
|
||||
def __init__(self, summa):
|
||||
super().__init__()
|
||||
self.summa_client = SummaHttpClient(**summa)
|
||||
self.waits.append(self.summa_client)
|
||||
|
||||
async def do(self, document_operation_pb: DocumentOperationPb) -> DocumentOperationPb:
|
||||
update_document_pb = document_operation_pb.update_document
|
||||
schema = update_document_pb.typed_document.WhichOneof('document')
|
||||
document = getattr(update_document_pb.typed_document, schema)
|
||||
original_id = getattr(document, 'original_id', None)
|
||||
if not update_document_pb.reindex or original_id:
|
||||
return document_operation_pb
|
||||
casted_document = MessageToDict(document, preserving_proto_field_name=True)
|
||||
# ToDo: Required to rework checking for extra fields in document
|
||||
# ToDo: It is needed to go to actual schema and load real fields and then check against them
|
||||
casted_document.pop('is_deleted', None)
|
||||
casted_document.pop('meta_language', None)
|
||||
casted_document.pop('type', None)
|
||||
await self.summa_client.put_document(schema, casted_document)
|
||||
if update_document_pb.commit:
|
||||
await self.summa_client.commit(schema)
|
||||
return document_operation_pb
|
@ -25,7 +25,6 @@ py3_image(
|
||||
requirement("aiodns"),
|
||||
requirement("aiohttp"),
|
||||
requirement("aiohttp_socks"),
|
||||
requirement("psycopg2-binary"),
|
||||
requirement("pytimeparse"),
|
||||
requirement("python_socks"),
|
||||
requirement("tenacity"),
|
||||
@ -39,7 +38,7 @@ py3_image(
|
||||
"//library/telegram",
|
||||
"//nexus/hub/aioclient",
|
||||
"//nexus/meta_api/aioclient",
|
||||
"//nexus/models/proto:models_proto_py",
|
||||
"//nexus/models/proto:proto_py",
|
||||
"//nexus/nlptools",
|
||||
"//nexus/views/telegram",
|
||||
requirement("izihawa_utils"),
|
||||
@ -50,7 +49,7 @@ container_push(
|
||||
name = "push-testing",
|
||||
format = "Docker",
|
||||
image = ":image",
|
||||
registry = "registry.example.com",
|
||||
registry = "registry.infra.svc.cluster.local",
|
||||
repository = "nexus-bot",
|
||||
tag = "testing",
|
||||
)
|
||||
@ -59,7 +58,7 @@ container_push(
|
||||
name = "push-latest",
|
||||
format = "Docker",
|
||||
image = ":image",
|
||||
registry = "registry.example.com",
|
||||
registry = "registry.infra.svc.cluster.local",
|
||||
repository = "nexus-bot",
|
||||
tag = "latest",
|
||||
)
|
||||
|
@ -20,13 +20,13 @@ class TelegramApplication(AioRootThing):
|
||||
mtproxy=self.config['telegram'].get('mtproxy'),
|
||||
)
|
||||
|
||||
self.hub_client = HubGrpcClient(base_url=self.config['hub']['url'])
|
||||
self.hub_client = HubGrpcClient(endpoint=self.config['hub']['endpoint'])
|
||||
self.starts.append(self.hub_client)
|
||||
self.idm_client = None
|
||||
if self.config['idm']['enabled']:
|
||||
self.idm_client = IdmApiGrpcClient(base_url=self.config['idm']['url'])
|
||||
self.idm_client = IdmApiGrpcClient(endpoint=self.config['idm']['endpoint'])
|
||||
self.starts.append(self.idm_client)
|
||||
self.meta_api_client = MetaApiGrpcClient(base_url=self.config['meta_api']['url'])
|
||||
self.meta_api_client = MetaApiGrpcClient(endpoint=self.config['meta_api']['endpoint'])
|
||||
self.starts.append(self.meta_api_client)
|
||||
|
||||
self.promotioner = Promotioner(promotions=self.config['promotions'])
|
||||
|
@ -12,13 +12,16 @@ application:
|
||||
bypass_maintenance: []
|
||||
# Debugging mode
|
||||
debug: true
|
||||
# Enabled indices (passed to Nexus Meta API)
|
||||
index_aliases:
|
||||
- scitech
|
||||
# All users (except `bypass_maintenance` ones) will get UPGRADE_MAINTENANCE message in response
|
||||
is_maintenance_mode: false
|
||||
# Disable /settings, uploading new articles (can be used while vacuuming backend Postgres)
|
||||
# and preventing creation of new users
|
||||
is_read_only_mode: false
|
||||
# Require subscription to `related_channel` before allowing to use the bot
|
||||
is_subscription_required: false
|
||||
is_subscription_required: true
|
||||
# Libera Pay URL in /donate message
|
||||
libera_pay_url:
|
||||
maintenance_picture_url:
|
||||
@ -27,9 +30,6 @@ application:
|
||||
page_size: 5
|
||||
# Length of generated Request-Id used for tracking requests across all backends
|
||||
request_id_length: 12
|
||||
# Enabled schemas (passed to Nexus Meta API)
|
||||
schemas:
|
||||
- scitech
|
||||
# Length of generated Session-ID used in commands to clue user sessions
|
||||
session_id_length: 8
|
||||
too_difficult_picture_url:
|
||||
@ -41,13 +41,13 @@ application:
|
||||
has_language_buttons: true
|
||||
has_system_messaging_button: true
|
||||
hub:
|
||||
url:
|
||||
endpoint:
|
||||
idm:
|
||||
enabled: false
|
||||
url:
|
||||
enabled: true
|
||||
endpoint:
|
||||
log_path: '/var/log/nexus-bot'
|
||||
meta_api:
|
||||
url:
|
||||
endpoint:
|
||||
metrics:
|
||||
enabled: false
|
||||
telegram:
|
||||
@ -56,9 +56,7 @@ telegram:
|
||||
# Telegram App ID from https://my.telegram.org/
|
||||
app_id: 00000
|
||||
# External bot name shown in messages to users
|
||||
bot_external_name: libgen_scihub_bot
|
||||
# Internal bot name used in logging
|
||||
bot_name: nexus-bot
|
||||
bot_name: libgen_scihub_1_bot
|
||||
bot_token:
|
||||
# WARNING! Potentially buggy telethon option. Sometimes it goes mad and overload users with tons of messages
|
||||
# Collect missed messages at startup time and answer to them
|
||||
|
@ -12,6 +12,7 @@ logging:
|
||||
handlers:
|
||||
debug:
|
||||
class: library.logging.handlers.BaseFileHandler
|
||||
formatter: default
|
||||
filename: '{{ log_path }}/debug.log'
|
||||
level: DEBUG
|
||||
error:
|
||||
|
@ -21,5 +21,5 @@ class UnknownFileFormatError(BaseError):
|
||||
code = 'unknown_file_format_error'
|
||||
|
||||
|
||||
class UnknownSchemaError(BaseError):
|
||||
code = 'unknown_schema_error'
|
||||
class UnknownIndexAliasError(BaseError):
|
||||
code = 'unknown_index_alias_error'
|
||||
|
@ -13,7 +13,7 @@ from library.logging import error_log
|
||||
from library.telegram.base import RequestContext
|
||||
from library.telegram.utils import safe_execution
|
||||
from nexus.bot.application import TelegramApplication
|
||||
from nexus.bot.exceptions import UnknownSchemaError
|
||||
from nexus.bot.exceptions import UnknownIndexAliasError
|
||||
from nexus.models.proto.typed_document_pb2 import \
|
||||
TypedDocument as TypedDocumentPb
|
||||
from nexus.translations import t
|
||||
@ -24,7 +24,10 @@ from telethon import (
|
||||
TelegramClient,
|
||||
events,
|
||||
)
|
||||
from telethon.errors import QueryIdInvalidError
|
||||
from telethon.errors import (
|
||||
QueryIdInvalidError,
|
||||
UserNotParticipantError,
|
||||
)
|
||||
|
||||
|
||||
def get_username(event: events.ChatAction, chat):
|
||||
@ -44,10 +47,6 @@ def is_banned(chat: ChatPb) -> bool:
|
||||
return chat.ban_until is not None and datetime.utcnow().timestamp() < chat.ban_until
|
||||
|
||||
|
||||
def is_subscribed(chat: ChatPb) -> bool:
|
||||
return chat.is_subscribed or chat.chat_id < 0 or chat.created_at > time.time() - 10 * 60
|
||||
|
||||
|
||||
class ReadOnlyModeError(BaseError):
|
||||
level = logging.WARNING
|
||||
code = 'read_only_mode_error'
|
||||
@ -68,11 +67,11 @@ class BaseHandler(ABC):
|
||||
|
||||
def __init__(self, application: TelegramApplication):
|
||||
self.application = application
|
||||
self.schema_to_resolver = {
|
||||
self.index_alias_to_resolver = {
|
||||
'scimag': self.resolve_scimag,
|
||||
'scitech': self.resolve_scitech,
|
||||
}
|
||||
self.short_schema_to_schema_dict = {
|
||||
self.short_index_alias_to_index_alias_dict = {
|
||||
'a': 'scimag',
|
||||
'b': 'scitech',
|
||||
}
|
||||
@ -80,19 +79,19 @@ class BaseHandler(ABC):
|
||||
def generate_session_id(self) -> str:
|
||||
return random_string(self.application.config['application']['session_id_length'])
|
||||
|
||||
def short_schema_to_schema(self, short_schema: str) -> str:
|
||||
return self.short_schema_to_schema_dict[short_schema]
|
||||
def short_index_alias_to_index_alias(self, short_index_alias: str) -> str:
|
||||
return self.short_index_alias_to_index_alias_dict[short_index_alias]
|
||||
|
||||
async def get_typed_document_pb(
|
||||
self,
|
||||
schema: str,
|
||||
index_alias: str,
|
||||
document_id: int,
|
||||
request_context: RequestContext,
|
||||
session_id: str,
|
||||
position: int,
|
||||
) -> TypedDocumentPb:
|
||||
return await self.application.meta_api_client.get(
|
||||
schema=schema,
|
||||
index_alias=index_alias,
|
||||
document_id=document_id,
|
||||
session_id=session_id,
|
||||
position=position,
|
||||
@ -108,7 +107,7 @@ class BaseHandler(ABC):
|
||||
session_id: str,
|
||||
) -> ScimagView:
|
||||
typed_document_pb = await self.get_typed_document_pb(
|
||||
schema='scimag',
|
||||
index_alias='scimag',
|
||||
document_id=document_id,
|
||||
position=position,
|
||||
request_context=request_context,
|
||||
@ -124,14 +123,14 @@ class BaseHandler(ABC):
|
||||
session_id: str,
|
||||
) -> ScitechView:
|
||||
typed_document_pb = await self.get_typed_document_pb(
|
||||
schema='scitech',
|
||||
index_alias='scitech',
|
||||
document_id=document_id,
|
||||
position=position,
|
||||
request_context=request_context,
|
||||
session_id=session_id,
|
||||
)
|
||||
search_response_duplicates = await self.application.meta_api_client.search(
|
||||
schemas=('scitech',),
|
||||
index_aliases=('scitech',),
|
||||
query=f'original_id:{document_id}',
|
||||
page_size=16,
|
||||
request_id=request_context.request_id,
|
||||
@ -149,16 +148,16 @@ class BaseHandler(ABC):
|
||||
|
||||
async def resolve_document(
|
||||
self,
|
||||
schema: str,
|
||||
index_alias: str,
|
||||
document_id: int,
|
||||
position: int,
|
||||
session_id: str,
|
||||
request_context: RequestContext
|
||||
) -> Union[ScimagView, ScitechView]:
|
||||
if schema not in self.schema_to_resolver:
|
||||
raise UnknownSchemaError()
|
||||
if index_alias not in self.index_alias_to_resolver:
|
||||
raise UnknownIndexAliasError(index_alias=index_alias)
|
||||
|
||||
resolver = self.schema_to_resolver[schema]
|
||||
resolver = self.index_alias_to_resolver[index_alias]
|
||||
return await resolver(
|
||||
document_id=document_id,
|
||||
position=position,
|
||||
@ -251,11 +250,23 @@ class BaseHandler(ABC):
|
||||
)
|
||||
raise events.StopPropagation()
|
||||
|
||||
async def is_subscribed(self, chat: ChatPb) -> bool:
|
||||
if chat.chat_id < 0 or chat.created_at > time.time() - 10 * 60:
|
||||
return True
|
||||
try:
|
||||
await self.application.telegram_client.get_permissions(
|
||||
self.application.config['telegram']['related_channel'],
|
||||
chat.chat_id,
|
||||
)
|
||||
except UserNotParticipantError:
|
||||
return False
|
||||
return True
|
||||
|
||||
async def _check_subscription(self, event: events.ChatAction, request_context: RequestContext, chat: ChatPb):
|
||||
if (
|
||||
self.application.config['application']['is_subscription_required']
|
||||
and self.is_subscription_required_for_handler
|
||||
and not is_subscribed(chat)
|
||||
and not await self.is_subscribed(chat)
|
||||
):
|
||||
async with safe_execution(
|
||||
request_context=request_context,
|
||||
@ -284,7 +295,6 @@ class BaseHandler(ABC):
|
||||
language='en',
|
||||
username=username,
|
||||
is_admin=False,
|
||||
is_subscribed=True,
|
||||
)
|
||||
return chat
|
||||
|
||||
|
@ -13,24 +13,24 @@ class DownloadHandler(BaseCallbackQueryHandler):
|
||||
is_group_handler = True
|
||||
|
||||
def parse_pattern(self, event: events.ChatAction):
|
||||
short_schema = event.pattern_match.group(1).decode()
|
||||
schema = self.short_schema_to_schema(short_schema)
|
||||
short_index_alias = event.pattern_match.group(1).decode()
|
||||
index_alias = self.short_index_alias_to_index_alias(short_index_alias)
|
||||
session_id = event.pattern_match.group(2).decode()
|
||||
document_id = int(event.pattern_match.group(3))
|
||||
position = int(event.pattern_match.group(4).decode())
|
||||
|
||||
return short_schema, schema, session_id, document_id, position
|
||||
return short_index_alias, index_alias, session_id, document_id, position
|
||||
|
||||
async def handler(self, event: events.ChatAction, request_context: RequestContext):
|
||||
short_schema, schema, session_id, document_id, position = self.parse_pattern(event)
|
||||
short_index_alias, index_alias, session_id, document_id, position = self.parse_pattern(event)
|
||||
|
||||
self.application.user_manager.last_widget[request_context.chat.chat_id] = None
|
||||
|
||||
request_context.add_default_fields(mode='download', session_id=session_id)
|
||||
request_context.statbox(action='get', document_id=document_id, position=position, schema=schema)
|
||||
request_context.statbox(action='get', document_id=document_id, position=position, index_alias=index_alias)
|
||||
|
||||
typed_document_pb = await self.get_typed_document_pb(
|
||||
schema=schema,
|
||||
index_alias=index_alias,
|
||||
document_id=document_id,
|
||||
request_context=request_context,
|
||||
session_id=session_id,
|
||||
@ -41,6 +41,7 @@ class DownloadHandler(BaseCallbackQueryHandler):
|
||||
chat=request_context.chat,
|
||||
request_id=request_context.request_id,
|
||||
session_id=session_id,
|
||||
bot_name=request_context.bot_name,
|
||||
)
|
||||
if start_delivery_response_pb.status == StartDeliveryResponsePb.Status.ALREADY_DOWNLOADING:
|
||||
await event.answer(
|
||||
|
@ -31,7 +31,7 @@ class RollHandler(BaseHandler):
|
||||
view, buttons = scitech_view.get_view(
|
||||
language=request_context.chat.language,
|
||||
session_id=session_id,
|
||||
bot_external_name=self.application.config['telegram']['bot_external_name'],
|
||||
bot_name=self.application.config['telegram']['bot_name'],
|
||||
)
|
||||
actions = [
|
||||
self.application.telegram_client.send_message(
|
||||
|
@ -27,7 +27,7 @@ from .base import (
|
||||
|
||||
class BaseSearchHandler(BaseHandler, ABC):
|
||||
def preprocess_query(self, query):
|
||||
return query.replace(f'@{self.application.config["telegram"]["bot_external_name"]}', '').strip()
|
||||
return query.replace(f'@{self.application.config["telegram"]["bot_name"]}', '').strip()
|
||||
|
||||
async def do_search(
|
||||
self,
|
||||
@ -109,7 +109,7 @@ class BaseSearchHandler(BaseHandler, ABC):
|
||||
document_view = parse_typed_document_to_view(scored_document.typed_document)
|
||||
# Second (re-)fetching is required to retrieve duplicates
|
||||
document_view = await self.resolve_document(
|
||||
schema=scored_document.typed_document.WhichOneof('document'),
|
||||
index_alias=scored_document.typed_document.WhichOneof('document'),
|
||||
document_id=document_view.id,
|
||||
position=0,
|
||||
session_id=session_id,
|
||||
@ -118,7 +118,7 @@ class BaseSearchHandler(BaseHandler, ABC):
|
||||
view, buttons = document_view.get_view(
|
||||
language=request_context.chat.language,
|
||||
session_id=session_id,
|
||||
bot_external_name=self.application.config['telegram']['bot_external_name'],
|
||||
bot_name=self.application.config['telegram']['bot_name'],
|
||||
with_buttons=not is_group_mode,
|
||||
)
|
||||
return await asyncio.gather(
|
||||
@ -254,7 +254,7 @@ class SearchPagingHandler(BaseCallbackQueryHandler):
|
||||
should_reset_last_widget = False
|
||||
|
||||
def preprocess_query(self, query):
|
||||
return query.replace(f'@{self.application.config["telegram"]["bot_external_name"]}', '').strip()
|
||||
return query.replace(f'@{self.application.config["telegram"]["bot_name"]}', '').strip()
|
||||
|
||||
def parse_pattern(self, event: events.ChatAction):
|
||||
session_id = event.pattern_match.group(1).decode()
|
||||
|
@ -17,7 +17,7 @@ class ShortlinkHandler(BaseHandler):
|
||||
request_context.statbox(action='start', mode='shortlink', query=query)
|
||||
|
||||
try:
|
||||
bot_name = self.application.config["telegram"]["bot_external_name"]
|
||||
bot_name = self.application.config["telegram"]["bot_name"]
|
||||
text = encode_query_to_deep_link(query, bot_name)
|
||||
except TooLongQueryError:
|
||||
text = t('TOO_LONG_QUERY_FOR_SHORTLINK', language=request_context.chat.language),
|
||||
|
@ -38,6 +38,7 @@ class SubmitHandler(BaseHandler):
|
||||
chat=request_context.chat,
|
||||
request_id=request_context.request_id,
|
||||
session_id=session_id,
|
||||
bot_name=request_context.bot_name,
|
||||
),
|
||||
event.delete(),
|
||||
)
|
||||
|
@ -18,8 +18,8 @@ class ViewHandler(BaseHandler):
|
||||
should_reset_last_widget = False
|
||||
|
||||
def parse_pattern(self, event: events.ChatAction):
|
||||
short_schema = event.pattern_match.group(1)
|
||||
schema = self.short_schema_to_schema(short_schema)
|
||||
short_index_alias = event.pattern_match.group(1)
|
||||
index_alias = self.short_index_alias_to_index_alias(short_index_alias)
|
||||
session_id = event.pattern_match.group(3)
|
||||
old_message_id = int(event.pattern_match.group(4))
|
||||
document_id = int(event.pattern_match.group(5))
|
||||
@ -27,7 +27,7 @@ class ViewHandler(BaseHandler):
|
||||
|
||||
page = int(position / self.application.config['application']['page_size'])
|
||||
|
||||
return schema, session_id, old_message_id, document_id, position, page
|
||||
return index_alias, session_id, old_message_id, document_id, position, page
|
||||
|
||||
async def process_widgeting(self, has_found_old_widget, old_message_id, request_context: RequestContext):
|
||||
if has_found_old_widget:
|
||||
@ -56,10 +56,10 @@ class ViewHandler(BaseHandler):
|
||||
return f'/search_{session_id}_{message_id}_{page}'
|
||||
|
||||
async def handler(self, event: events.ChatAction, request_context: RequestContext):
|
||||
schema, session_id, old_message_id, document_id, position, page = self.parse_pattern(event)
|
||||
index_alias, session_id, old_message_id, document_id, position, page = self.parse_pattern(event)
|
||||
|
||||
request_context.add_default_fields(mode='view', session_id=session_id)
|
||||
request_context.statbox(action='view', document_id=document_id, position=position, schema=schema)
|
||||
request_context.statbox(action='view', document_id=document_id, position=position, index_alias=index_alias)
|
||||
|
||||
has_found_old_widget = old_message_id == self.application.user_manager.last_widget.get(request_context.chat.chat_id)
|
||||
|
||||
@ -71,7 +71,7 @@ class ViewHandler(BaseHandler):
|
||||
)
|
||||
|
||||
document_view = await self.resolve_document(
|
||||
schema,
|
||||
index_alias,
|
||||
document_id,
|
||||
position,
|
||||
session_id,
|
||||
@ -91,7 +91,7 @@ class ViewHandler(BaseHandler):
|
||||
view, buttons = document_view.get_view(
|
||||
language=request_context.chat.language,
|
||||
session_id=session_id,
|
||||
bot_external_name=self.application.config['telegram']['bot_external_name'],
|
||||
bot_name=self.application.config['telegram']['bot_name'],
|
||||
position=position,
|
||||
back_command=back_command,
|
||||
)
|
||||
|
@ -16,24 +16,24 @@ class VoteHandler(BaseCallbackQueryHandler):
|
||||
filter = events.CallbackQuery(pattern='^/vote([ab])?_([A-Za-z0-9]+)_([0-9]+)_([bo])$')
|
||||
|
||||
def parse_pattern(self, event: events.ChatAction):
|
||||
short_schema = event.pattern_match.group(1)
|
||||
schema = self.short_schema_to_schema(short_schema.decode()) if short_schema else None
|
||||
short_index_alias = event.pattern_match.group(1)
|
||||
index_alias = self.short_index_alias_to_index_alias(short_index_alias.decode()) if short_index_alias else None
|
||||
session_id = event.pattern_match.group(2).decode()
|
||||
document_id = int(event.pattern_match.group(3).decode())
|
||||
vote = event.pattern_match.group(4).decode()
|
||||
vote_value = {'b': -1, 'o': 1}[vote]
|
||||
|
||||
return schema, session_id, document_id, vote, vote_value
|
||||
return index_alias, session_id, document_id, vote, vote_value
|
||||
|
||||
async def handler(self, event: events.ChatAction, request_context: RequestContext):
|
||||
schema, session_id, document_id, vote, vote_value = self.parse_pattern(event)
|
||||
index_alias, session_id, document_id, vote, vote_value = self.parse_pattern(event)
|
||||
|
||||
request_context.add_default_fields(mode='vote', session_id=session_id)
|
||||
request_context.statbox(
|
||||
action='vote',
|
||||
document_id=document_id,
|
||||
query=vote,
|
||||
schema=schema,
|
||||
index_alias=index_alias,
|
||||
)
|
||||
|
||||
document_operation_pb = DocumentOperationPb(
|
||||
@ -44,7 +44,7 @@ class VoteHandler(BaseCallbackQueryHandler):
|
||||
),
|
||||
)
|
||||
logging.getLogger('operation').info(
|
||||
msg=MessageToDict(document_operation_pb),
|
||||
msg=MessageToDict(document_operation_pb, preserving_proto_field_name=True),
|
||||
)
|
||||
|
||||
message = await event.get_message()
|
||||
|
@ -64,7 +64,7 @@ class SearchWidget:
|
||||
|
||||
async def _acquire_documents(self):
|
||||
self._search_response = await self.application.meta_api_client.search(
|
||||
schemas=self.application.config['application']['schemas'],
|
||||
index_aliases=self.application.config['application']['index_aliases'],
|
||||
query=self.query,
|
||||
page=self.page,
|
||||
page_size=self.application.config['application']['page_size'],
|
||||
@ -87,7 +87,7 @@ class SearchWidget:
|
||||
return t('COULD_NOT_FIND_ANYTHING', language=self.chat.language), [close_button(self.session_id)]
|
||||
|
||||
serp_elements = []
|
||||
bot_external_name = self.application.config['telegram']['bot_external_name']
|
||||
bot_name = self.application.config['telegram']['bot_name']
|
||||
|
||||
for scored_document in self.scored_documents:
|
||||
view = parse_typed_document_to_view(scored_document.typed_document)
|
||||
@ -98,7 +98,7 @@ class SearchWidget:
|
||||
position=scored_document.position,
|
||||
)
|
||||
else:
|
||||
view_command = view.get_deep_link(bot_external_name, text='⬇️')
|
||||
view_command = view.get_deep_link(bot_name, text='⬇️')
|
||||
serp_elements.append(
|
||||
view.get_snippet(
|
||||
language=self.chat.language,
|
||||
@ -112,18 +112,18 @@ class SearchWidget:
|
||||
try:
|
||||
encoded_query = encode_query_to_deep_link(
|
||||
self.query,
|
||||
bot_external_name,
|
||||
bot_name,
|
||||
)
|
||||
serp = (
|
||||
f"{serp}\n\n**{t('DOWNLOAD_AND_SEARCH_MORE', language=self.chat.language)}: **"
|
||||
f'[@{bot_external_name}]'
|
||||
f'[@{bot_name}]'
|
||||
f'({encoded_query})'
|
||||
)
|
||||
except TooLongQueryError:
|
||||
serp = (
|
||||
f"{serp}\n\n**{t('DOWNLOAD_AND_SEARCH_MORE', language=self.chat.language)}: **"
|
||||
f'[@{bot_external_name}]'
|
||||
f'(https://t.me/{bot_external_name})'
|
||||
f'[@{bot_name}]'
|
||||
f'(https://t.me/{bot_name})'
|
||||
)
|
||||
|
||||
if not self.is_group_mode:
|
||||
|
@ -1,21 +1,21 @@
|
||||
---
|
||||
# yamllint disable rule:key-ordering
|
||||
default_fields: ["abstract", "authors", "language", "title", "tags", "year"]
|
||||
enabled: true
|
||||
default_fields: ["abstract", "authors", "language", "title", "tags"]
|
||||
key_field: "id"
|
||||
multi_fields: ["authors", "ipfs_multihashes", "issns", "references", "tags"]
|
||||
name: scimag
|
||||
schema:
|
||||
- name: id
|
||||
type: i64
|
||||
options:
|
||||
fast: single
|
||||
fieldnorms: false
|
||||
indexed: true
|
||||
stored: true
|
||||
- name: abstract
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: position
|
||||
tokenizer: summa
|
||||
stored: true
|
||||
@ -23,6 +23,7 @@ schema:
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: position
|
||||
tokenizer: summa
|
||||
stored: true
|
||||
@ -30,18 +31,21 @@ schema:
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: basic
|
||||
tokenizer: raw
|
||||
stored: true
|
||||
- name: first_page
|
||||
type: i64
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: false
|
||||
stored: true
|
||||
- name: container_title
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: position
|
||||
tokenizer: summa
|
||||
stored: true
|
||||
@ -58,41 +62,48 @@ schema:
|
||||
- name: issued_at
|
||||
type: i64
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: true
|
||||
stored: true
|
||||
- name: language
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: basic
|
||||
tokenizer: raw
|
||||
stored: true
|
||||
- name: last_page
|
||||
type: i64
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: false
|
||||
stored: true
|
||||
- name: ref_by_count
|
||||
type: i64
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: false
|
||||
stored: true
|
||||
- name: references
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: basic
|
||||
tokenizer: raw
|
||||
stored: false
|
||||
- name: scimag_bulk_id
|
||||
type: i64
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: false
|
||||
stored: true
|
||||
- name: tags
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: position
|
||||
tokenizer: summa
|
||||
stored: true
|
||||
@ -100,12 +111,14 @@ schema:
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: position
|
||||
tokenizer: summa
|
||||
stored: true
|
||||
- name: updated_at
|
||||
type: i64
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: true
|
||||
stored: true
|
||||
- name: volume
|
||||
@ -114,9 +127,8 @@ schema:
|
||||
indexing: null
|
||||
stored: true
|
||||
- name: year
|
||||
type: text
|
||||
type: i64
|
||||
options:
|
||||
indexing:
|
||||
record: basic
|
||||
tokenizer: raw
|
||||
stored: false
|
||||
fieldnorms: true
|
||||
indexed: true
|
||||
stored: true
|
@ -1,21 +1,21 @@
|
||||
---
|
||||
# yamllint disable rule:key-ordering
|
||||
default_fields: ["authors", "description", "doi", "tags", "title", "year"]
|
||||
enabled: true
|
||||
default_fields: ["authors", "description", "tags", "title"]
|
||||
key_field: "id"
|
||||
multi_fields: ["authors", "ipfs_multihashes", "isbns", "tags"]
|
||||
name: scitech
|
||||
schema:
|
||||
- name: id
|
||||
type: i64
|
||||
options:
|
||||
fast: single
|
||||
fieldnorms: false
|
||||
indexed: true
|
||||
stored: true
|
||||
- name: authors
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: position
|
||||
tokenizer: summa
|
||||
stored: true
|
||||
@ -33,6 +33,7 @@ schema:
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: position
|
||||
tokenizer: summa
|
||||
stored: true
|
||||
@ -40,6 +41,7 @@ schema:
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: basic
|
||||
tokenizer: raw
|
||||
stored: true
|
||||
@ -47,28 +49,33 @@ schema:
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: basic
|
||||
tokenizer: raw
|
||||
stored: true
|
||||
- name: fiction_id
|
||||
type: i64
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: false
|
||||
stored: true
|
||||
- name: filesize
|
||||
type: i64
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: false
|
||||
stored: true
|
||||
- name: ipfs_multihashes
|
||||
type: text
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: false
|
||||
stored: true
|
||||
- name: isbns
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: basic
|
||||
tokenizer: raw
|
||||
stored: true
|
||||
@ -76,28 +83,33 @@ schema:
|
||||
type: i64
|
||||
options:
|
||||
fast: single
|
||||
fieldnorms: false
|
||||
indexed: true
|
||||
stored: true
|
||||
- name: has_duplicates
|
||||
type: i64
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: false
|
||||
stored: true
|
||||
- name: language
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: basic
|
||||
tokenizer: raw
|
||||
stored: true
|
||||
- name: libgen_id
|
||||
type: i64
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: false
|
||||
stored: true
|
||||
- name: original_id
|
||||
type: i64
|
||||
options:
|
||||
fieldnorms: false
|
||||
indexed: true
|
||||
stored: true
|
||||
- name: pages
|
||||
@ -119,6 +131,7 @@ schema:
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: position
|
||||
tokenizer: summa
|
||||
stored: true
|
||||
@ -126,6 +139,7 @@ schema:
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: position
|
||||
tokenizer: summa
|
||||
stored: true
|
||||
@ -133,6 +147,7 @@ schema:
|
||||
type: text
|
||||
options:
|
||||
indexing:
|
||||
fieldnorms: true
|
||||
record: position
|
||||
tokenizer: summa
|
||||
stored: true
|
||||
@ -140,6 +155,7 @@ schema:
|
||||
type: i64
|
||||
options:
|
||||
fast: single
|
||||
fieldnorms: false
|
||||
indexed: true
|
||||
stored: true
|
||||
- name: volume
|
||||
@ -148,9 +164,8 @@ schema:
|
||||
indexing: null
|
||||
stored: true
|
||||
- name: year
|
||||
type: text
|
||||
type: i64
|
||||
options:
|
||||
indexing:
|
||||
record: basic
|
||||
tokenizer: raw
|
||||
stored: false
|
||||
fieldnorms: true
|
||||
indexed: true
|
||||
stored: true
|
@ -1,16 +0,0 @@
|
||||
---
|
||||
|
||||
http:
|
||||
address: 0.0.0.0
|
||||
keep_alive_secs: 75
|
||||
max_body_size_mb: 32
|
||||
port: 80
|
||||
workers: 48
|
||||
log_path: /var/log/nexus-cognitron
|
||||
search_engine:
|
||||
auto_commit: false
|
||||
data_path: /nexus-cognitron/summa
|
||||
default_page_size: 5
|
||||
timeout_secs: 15
|
||||
writer_memory_mb: 1024
|
||||
writer_threads: 4
|
@ -1,20 +0,0 @@
|
||||
load("@pip_modules//:requirements.bzl", "requirement")
|
||||
load("@rules_python//python:defs.bzl", "py_binary")
|
||||
|
||||
py_binary(
|
||||
name = "installer",
|
||||
srcs = glob([
|
||||
"**/*.py",
|
||||
]),
|
||||
imports = ["."],
|
||||
main = "main.py",
|
||||
srcs_version = "PY3",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
requirement("aioipfs"),
|
||||
requirement("fire"),
|
||||
requirement("pyyaml"),
|
||||
requirement("tantipy"),
|
||||
requirement("izihawa_utils"),
|
||||
],
|
||||
)
|
@ -1,11 +0,0 @@
|
||||
import time
|
||||
|
||||
import fire
|
||||
from nexus.cognitron.installer.scripts.iterate import iterate
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = time.time()
|
||||
fire.Fire({
|
||||
'iterate': iterate,
|
||||
})
|
||||
print(f'Elapsed {time.time() - start:.2f} secs')
|
@ -1,9 +0,0 @@
|
||||
import os
|
||||
|
||||
|
||||
def resolve_path(filepath):
|
||||
if os.path.isabs(filepath):
|
||||
return filepath
|
||||
cwd = os.environ.get('BUILD_WORKING_DIRECTORY', os.getcwd())
|
||||
filepath = os.path.join(cwd, filepath)
|
||||
return filepath
|
@ -1,46 +0,0 @@
|
||||
import glob
|
||||
import multiprocessing
|
||||
import os
|
||||
from functools import partial
|
||||
|
||||
import yaml
|
||||
from izihawa_utils.itertools import ichunks
|
||||
from tantipy import (
|
||||
TantivyCoder,
|
||||
TantivyReader,
|
||||
)
|
||||
|
||||
from .common import resolve_path
|
||||
|
||||
|
||||
def work(document):
|
||||
# ToDo: Replace this function to what you want to do with document
|
||||
print(document)
|
||||
|
||||
|
||||
def _do_work(coder, chunk_size, limit, store_filepath):
|
||||
with open(store_filepath, 'rb') as file:
|
||||
data = file.read()
|
||||
print(f'Processing segment {store_filepath}, size: {len(data) / (1024 * 1024):.2f} Mb ...')
|
||||
tr = TantivyReader(data, coder=coder)
|
||||
for chunk_num, documents in enumerate(ichunks(tr.documents(), chunk_size)):
|
||||
for doc_num, document in enumerate(documents):
|
||||
if limit and chunk_num * chunk_size + doc_num > limit:
|
||||
print(f'Segment {store_filepath} early terminated due to limits')
|
||||
return
|
||||
work(document)
|
||||
print(f'Segment {store_filepath} successfully processed')
|
||||
|
||||
|
||||
def iterate(data_filepath, schema_filepath, processes=8, chunk_size=100, limit=1):
|
||||
data_filepath = resolve_path(data_filepath)
|
||||
schema_filepath = resolve_path(schema_filepath)
|
||||
|
||||
with open(schema_filepath) as schema_file:
|
||||
coder = TantivyCoder(yaml.safe_load(schema_file.read()))
|
||||
|
||||
store_filepaths = glob.glob(os.path.join(data_filepath, '*.store'))
|
||||
|
||||
print(f'Total segments: {len(store_filepaths)}')
|
||||
pool = multiprocessing.Pool(processes)
|
||||
pool.map(partial(_do_work, coder, chunk_size, limit), store_filepaths)
|
@ -1,51 +1,43 @@
|
||||
load("@io_bazel_rules_docker//container:container.bzl", "container_push")
|
||||
load("@io_bazel_rules_docker//nodejs:image.bzl", "nodejs_image")
|
||||
load("@npm//nuxt:index.bzl", "nuxt")
|
||||
load("@npm//nuxt3:index.bzl", "nuxi")
|
||||
|
||||
files = ["nuxt.config.js"] + glob([
|
||||
"assets/**",
|
||||
files = [
|
||||
"app.vue",
|
||||
"nuxt.config.ts",
|
||||
] + glob([
|
||||
"components/**/*.vue",
|
||||
"layouts/*.vue",
|
||||
"middleware/*.js",
|
||||
"pages/**/*.vue",
|
||||
"plugins/*.js",
|
||||
"static/*",
|
||||
"store/*.js",
|
||||
"layouts/**/*.vue",
|
||||
"plugins/**/*.js",
|
||||
])
|
||||
|
||||
deps = [
|
||||
"@npm//@nuxtjs/axios",
|
||||
"@npm//bootstrap",
|
||||
"@npm//bootstrap-vue",
|
||||
"@npm//core-js",
|
||||
"@npm//dateformat",
|
||||
"@npm//electron",
|
||||
"@npm//axios",
|
||||
"@npm//bootstrap-vue-3",
|
||||
"@npm//pug",
|
||||
"@npm//pug-plain-loader",
|
||||
"@npm//sass",
|
||||
"@npm//sass-loader",
|
||||
"@npm//vue",
|
||||
"@npm//@types/node",
|
||||
"//nexus/meta_api/js/client",
|
||||
"//nexus/views/js",
|
||||
]
|
||||
|
||||
nuxt(
|
||||
nuxi(
|
||||
name = "web-dev",
|
||||
args = [
|
||||
"-c",
|
||||
"nexus/cognitron/web/nuxt.config.js",
|
||||
"--watch-poll",
|
||||
"dev",
|
||||
"nexus/cognitron/web",
|
||||
],
|
||||
data = files + deps,
|
||||
)
|
||||
|
||||
nuxt(
|
||||
name = ".nuxt",
|
||||
nuxi(
|
||||
name = ".output",
|
||||
args = [
|
||||
"build",
|
||||
"--standalone",
|
||||
"-c",
|
||||
"nexus/cognitron/web/nuxt.config.js",
|
||||
"nexus/cognitron/web",
|
||||
"--buildDir=$(@D)",
|
||||
],
|
||||
data = files + deps,
|
||||
@ -55,19 +47,8 @@ nuxt(
|
||||
nodejs_image(
|
||||
name = "image",
|
||||
base = "//images/production:base-nodejs-image",
|
||||
data = glob(["static/*"]) + [
|
||||
"nuxt.config.js",
|
||||
":.nuxt",
|
||||
"@npm//@nuxtjs/axios",
|
||||
"@npm//bootstrap-vue",
|
||||
"@npm//nuxt",
|
||||
],
|
||||
entry_point = "@npm//:node_modules/nuxt/bin/nuxt.js",
|
||||
templated_args = [
|
||||
"start",
|
||||
"-c",
|
||||
"nexus/cognitron/web/nuxt.config.js",
|
||||
],
|
||||
data = [":.output"],
|
||||
entry_point = ".output/server/index.mjs",
|
||||
)
|
||||
|
||||
|
||||
|
@ -1,6 +1,29 @@
|
||||
# Nexus Web
|
||||
# Nuxt 3 Minimal Starter
|
||||
|
||||
#### Development
|
||||
```shell script
|
||||
bazel run web-dev
|
||||
We recommend to look at the [documentation](https://v3.nuxtjs.org).
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure to install the dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
Start the development server on http://localhost:3000
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
## Production
|
||||
|
||||
Build the application for production:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
Checkout the [deployment documentation](https://v3.nuxtjs.org/docs/deployment).
|
4
nexus/cognitron/web/app.vue
Normal file
@ -0,0 +1,4 @@
|
||||
<template lang="pug">
|
||||
div
|
||||
NuxtWelcome
|
||||
</template>
|
@ -1,41 +0,0 @@
|
||||
.btn {
|
||||
border-radius: 0 !important; // sass-lint:disable-line no-important
|
||||
padding: 0 2em !important; // sass-lint:disable-line no-important
|
||||
}
|
||||
|
||||
.pagination {
|
||||
li {
|
||||
padding-left: 0 !important; // sass-lint:disable-line no-important
|
||||
|
||||
&::after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$primary: #1a95e0;
|
||||
|
||||
@import 'bootstrap/scss/bootstrap';
|
||||
|
||||
body {
|
||||
font-size: 13px !important; // sass-lint:disable-line no-important
|
||||
line-height: 1.3em !important; // sass-lint:disable-line no-important
|
||||
}
|
||||
|
||||
html {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
a {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
label {
|
||||
span {
|
||||
line-height: 2em;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<template lang="pug">
|
||||
div.document
|
||||
div.document
|
||||
v-scimag(v-if="document.schema === 'scimag'" :document="document")
|
||||
v-scitech(v-if="document.schema === 'scitech'" :document="document")
|
||||
</template>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<template lang="pug">
|
||||
ul
|
||||
ul
|
||||
li(v-for='document in documents')
|
||||
v-scimag-search-item(v-if="document.schema == 'scimag'", :document='document', :key='document.id')
|
||||
v-scitech-search-item(v-if="document.schema == 'scitech'", :document='document', :key='document.id')
|
||||
v-scimag-search-item(v-if="document.index_alias == 'scimag'", :document='document', :key='document.id')
|
||||
v-scitech-search-item(v-if="document.index_alias == 'scitech'", :document='document', :key='document.id')
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template lang="pug">
|
||||
nav.navbar.fixed-bottom.ml-auto
|
||||
nav.navbar.fixed-bottom.ml-auto
|
||||
ul.navbar-nav.ml-auto
|
||||
li.nav-item
|
||||
| Powered by
|
||||
@ -17,7 +17,3 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template lang="pug">
|
||||
nav.navbar.navbar-light.bg-light
|
||||
nav.navbar.navbar-light.bg-light
|
||||
b-container
|
||||
nuxt-link(to="/" title="Go to search!").logo
|
||||
| > Nexus Cognitron
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template lang="pug">
|
||||
div.d-flex
|
||||
div.d-flex
|
||||
div
|
||||
nuxt-link(:to="{ name: 'documents-schema-id', params: { schema: document.schema, id: document.id }}") {{ document.icon }} {{ document.title }}
|
||||
nuxt-link(:to="{ name: 'documents-index-name-id', params: { schema: document.schema, id: document.id }}") {{ document.icon }} {{ document.title }}
|
||||
.detail
|
||||
div
|
||||
i.mr-1 DOI:
|
||||
@ -10,7 +10,6 @@
|
||||
span {{ document.getFirstAuthors(false, 1) }} {{ issuedAt }}
|
||||
.gp
|
||||
span.el.text-uppercase {{ document.getFormattedFiledata() }}
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template lang="pug">
|
||||
div
|
||||
div
|
||||
.top
|
||||
h6 {{ document.title }}
|
||||
.top
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template lang="pug">
|
||||
div.d-flex
|
||||
div.d-flex
|
||||
div
|
||||
nuxt-link(:to="{ name: 'documents-schema-id', params: { schema: document.schema, id: document.id }}") {{ document.icon }} {{ document.title }}
|
||||
nuxt-link(:to="{ name: 'documents-index-name-id', params: { index_alias: document.index_alias, id: document.id }}") {{ document.icon }} {{ document.title }}
|
||||
.detail
|
||||
div
|
||||
i.mr-1(v-if='document.doi') DOI:
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template lang="pug">
|
||||
div
|
||||
div
|
||||
.top
|
||||
h6 {{ document.title }}
|
||||
.top
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template lang="pug">
|
||||
tr
|
||||
tr
|
||||
th {{ label }}
|
||||
td
|
||||
a(v-for="link in links" :href="link.url" download) {{ link.value }}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template lang="pug">
|
||||
tr(v-show="value")
|
||||
tr(v-show="value")
|
||||
th {{ label }}
|
||||
td(:class="valueClasses")
|
||||
| {{ formattedValue }}
|
||||
|
@ -1,7 +0,0 @@
|
||||
<template lang="pug">
|
||||
div
|
||||
v-header
|
||||
b-container.mt-3
|
||||
nuxt
|
||||
v-footer
|
||||
</template>
|
@ -1,90 +0,0 @@
|
||||
let buildDir = process.argv.find((s) => s.startsWith('--buildDir='))
|
||||
if (buildDir) {
|
||||
buildDir = buildDir.substr('--buildDir='.length)
|
||||
} else {
|
||||
buildDir = 'nexus/cognitron/web/.nuxt'
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
server: {
|
||||
host: process.env['NEXUS_COGNITRON_WEB_application.address'] || '0.0.0.0',
|
||||
port: process.env['NEXUS_COGNITRON_WEB_application.port'] || 3000
|
||||
},
|
||||
buildDir: buildDir,
|
||||
srcDir: 'nexus/cognitron/web',
|
||||
modulesDir: ['external/' + process.env.BAZEL_NODE_MODULES_ROOT],
|
||||
head: {
|
||||
title: 'Nexus Cognitron',
|
||||
meta: [
|
||||
{ charset: 'utf-8' },
|
||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
||||
{ hid: 'description', name: 'description', content: 'Biggest Library on both Earth and Mars' }
|
||||
],
|
||||
link: [
|
||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
|
||||
{ rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' },
|
||||
{ rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32x32.png' },
|
||||
{ rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon-16x16.png' },
|
||||
{ rel: 'manifest', href: '/site.webmanifest' },
|
||||
{ rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#5bbad5' },
|
||||
{ name: 'msapplication-TileColor', content: '#603cba' },
|
||||
{ name: 'theme-color', content: '#ffffff' }
|
||||
]
|
||||
},
|
||||
|
||||
// Global CSS (https://go.nuxtjs.dev/config-css)
|
||||
css: [
|
||||
'@/assets/css/app.scss',
|
||||
'@/assets/css/terminal.css'
|
||||
],
|
||||
|
||||
publicRuntimeConfig: {
|
||||
meta_api: {
|
||||
hostname: process.env['NEXUS_COGNITRON_WEB_meta_api.hostname'],
|
||||
url: process.env['NEXUS_COGNITRON_WEB_meta_api.url']
|
||||
},
|
||||
ipfs: {
|
||||
gateway: {
|
||||
url: process.env['NEXUS_COGNITRON_WEB_ipfs.gateway.url'] || 'https://ipfs.io'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
|
||||
plugins: [
|
||||
'plugins/helpers',
|
||||
{ src: 'plugins/meta-api', mode: 'client' },
|
||||
'plugins/utils'
|
||||
],
|
||||
|
||||
// Auto import components (https://go.nuxtjs.dev/config-components)
|
||||
components: true,
|
||||
|
||||
// Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules)
|
||||
buildModules: [],
|
||||
|
||||
// Modules (https://go.nuxtjs.dev/config-modules)
|
||||
modules: [
|
||||
'@nuxtjs/axios',
|
||||
// https://go.nuxtjs.dev/bootstrap
|
||||
'bootstrap-vue/nuxt'
|
||||
],
|
||||
|
||||
loading: { color: '#1a95e0', throttle: 0 },
|
||||
watchers: {
|
||||
webpack: {
|
||||
poll: true
|
||||
}
|
||||
},
|
||||
|
||||
// Build Configuration (https://go.nuxtjs.dev/config-build)
|
||||
build: {
|
||||
extend (config) {
|
||||
config.resolve.alias['~'] = process.cwd()
|
||||
},
|
||||
transpile: ['nexus-meta-api-js-client', 'nexus-views-js']
|
||||
},
|
||||
node: {
|
||||
window: 'empty'
|
||||
}
|
||||
}
|
33
nexus/cognitron/web/nuxt.config.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { defineNuxtConfig } from 'nuxt3'
|
||||
|
||||
let buildDir = process.argv.find((s) => s.startsWith('--buildDir='))
|
||||
if (buildDir) {
|
||||
buildDir = buildDir.substr('--buildDir='.length)
|
||||
}
|
||||
|
||||
export default defineNuxtConfig({
|
||||
head: {
|
||||
title: 'Nexus Cognitron',
|
||||
meta: [
|
||||
{ charset: 'utf-8' },
|
||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
||||
{ hid: 'description', name: 'description', content: 'Biggest Library on both Earth and Mars' }
|
||||
],
|
||||
link: [
|
||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
|
||||
{ rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' },
|
||||
{ rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32x32.png' },
|
||||
{ rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon-16x16.png' },
|
||||
{ rel: 'manifest', href: '/site.webmanifest' },
|
||||
{ rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#5bbad5' },
|
||||
{ name: 'msapplication-TileColor', content: '#603cba' },
|
||||
{ name: 'theme-color', content: '#ffffff' }
|
||||
]
|
||||
},
|
||||
nitro: {
|
||||
preset: 'server',
|
||||
output: {
|
||||
dir: buildDir,
|
||||
}
|
||||
}
|
||||
})
|
@ -1,22 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<document
|
||||
v-if="document"
|
||||
:document="document"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
document: {}
|
||||
}
|
||||
},
|
||||
async fetch () {
|
||||
this.document = await this.$meta_api.get(this.$route.params.schema, this.$route.params.id)
|
||||
},
|
||||
fetchOnServer: false
|
||||
}
|
||||
</script>
|
@ -1,101 +0,0 @@
|
||||
<template lang="pug">
|
||||
div
|
||||
form
|
||||
.input-group
|
||||
b-form-input(v-model='query' placeholder='Enter book name or DOI')
|
||||
b-button(type='submit' @click.stop.prevent='submit(query, 1, schemas)') Search
|
||||
b-form-checkbox-group.checkbox-group(
|
||||
v-model="schemas"
|
||||
:options="availableSchemas"
|
||||
value-field="item"
|
||||
text-field="name")
|
||||
p.mt-5(v-if="nothingFound") Nothing found
|
||||
.search-list
|
||||
search-list(:documents='documents')
|
||||
b-pagination(v-if='documents.length > 0' v-model='page' :total-rows='totalRows' :per-page='perPage' limit="2" :disabled="isLoading")
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SearchList from '@/components/search-list'
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: { SearchList },
|
||||
loading: true,
|
||||
data () {
|
||||
return {
|
||||
availableSchemas: [
|
||||
{ item: 'scitech', name: 'SciTech' },
|
||||
{ item: 'scimag', name: 'SciMag' }
|
||||
],
|
||||
documents: [],
|
||||
nothingFound: false,
|
||||
page: 1,
|
||||
perPage: 1,
|
||||
query: '',
|
||||
schemas: ['scimag', 'scitech'],
|
||||
totalRows: 10
|
||||
}
|
||||
},
|
||||
|
||||
async fetch () {
|
||||
this.nothingFound = false
|
||||
this.query = this.$route.query.query
|
||||
if (!this.query) {
|
||||
this.documents = []
|
||||
return this.$router.push({ path: '/' })
|
||||
}
|
||||
this.schemas = this.$route.query.schemas.split(',')
|
||||
if (this.schemas.length === 0) {
|
||||
this.schemas = ['scimag', 'scitech']
|
||||
}
|
||||
|
||||
this.page = this.$route.query.page
|
||||
await this.retrieveDocuments()
|
||||
},
|
||||
fetchOnServer: false,
|
||||
computed: {
|
||||
isLoading () {
|
||||
return this.$fetchState.pending || false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route.query': '$fetch',
|
||||
async schemas () {
|
||||
if (this.query) {
|
||||
await this.submit(this.query, 1, this.schemas)
|
||||
}
|
||||
},
|
||||
async page () {
|
||||
await this.submit(this.query, this.page, this.schemas)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async submit (query, page, schemas) {
|
||||
await this.$router.push({ path: '/', query: { query: query, page: page, schemas: schemas.join(',') } })
|
||||
},
|
||||
async retrieveDocuments () {
|
||||
const response = await this.$meta_api.search(this.schemas, this.query, this.page - 1, 5)
|
||||
if (response.hasNext) {
|
||||
this.totalRows = Number(this.page) + 1
|
||||
} else {
|
||||
this.totalRows = this.page
|
||||
}
|
||||
if (response.documents.length === 0) {
|
||||
this.nothingFound = true
|
||||
}
|
||||
this.documents = response.documents
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.search-list {
|
||||
padding-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
.checkbox-group {
|
||||
margin: 10px 0;
|
||||
}
|
||||
</style>
|
20
nexus/cognitron/web/plugins/meta-api.js
Executable file → Normal file
@ -5,10 +5,10 @@ function getSchema (typedDocument) {
|
||||
return Object.keys(typedDocument).filter(k => typedDocument[k] !== undefined)[0]
|
||||
}
|
||||
|
||||
function schemaToView (schema, pb) {
|
||||
if (schema === 'scimag') {
|
||||
function indexNameToView (indexName, pb) {
|
||||
if (indexName === 'scimag') {
|
||||
return new ScimagView(pb)
|
||||
} else if (schema === 'scitech') {
|
||||
} else if (indexName === 'scitech') {
|
||||
return new ScitechView(pb)
|
||||
}
|
||||
}
|
||||
@ -18,16 +18,16 @@ class MetaApiWrapper {
|
||||
this.metaApi = new MetaApi(metaApiConfig.url || ('http://' + window.location.host), metaApiConfig.hostname)
|
||||
}
|
||||
|
||||
async get (schema, id) {
|
||||
const response = await this.metaApi.get(schema, id)
|
||||
return schemaToView(schema, response[schema])
|
||||
async get (indexName, id) {
|
||||
const response = await this.metaApi.get(indexName, id)
|
||||
return indexNameToView(indexName, response[indexName])
|
||||
}
|
||||
|
||||
async search (schemas, query, page, pageSize) {
|
||||
const response = await this.metaApi.search(schemas, query, page, pageSize)
|
||||
async search (names, query, page, pageSize) {
|
||||
const response = await this.metaApi.search(names, query, page, pageSize)
|
||||
const documents = response.scoredDocumentsList.map((scoredDocument) => {
|
||||
const schema = getSchema(scoredDocument.typedDocument)
|
||||
return schemaToView(schema, scoredDocument.typedDocument[schema])
|
||||
const indexName = getSchema(scoredDocument.typedDocument)
|
||||
return indexNameToView(indexName, scoredDocument.typedDocument[indexName])
|
||||
})
|
||||
return {
|
||||
hasNext: response.hasNext,
|
||||
|
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 367 KiB |
Before Width: | Height: | Size: 51 KiB |
@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<TileColor>#603cba</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 31 KiB |
@ -1,932 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="640.000000pt" height="640.000000pt" viewBox="0 0 640.000000 640.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,640.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M2 6365 c0 -23 4 -35 12 -32 6 2 10 12 8 22 -3 13 1 16 14 11 10 -4
|
||||
21 0 28 9 8 11 15 12 26 4 11 -8 12 -12 3 -16 -25 -10 -12 -21 22 -20 33 1 52
|
||||
17 20 17 -8 0 -15 5 -15 10 0 6 6 10 13 8 7 -2 15 2 17 7 3 6 -25 11 -71 13
|
||||
l-77 3 0 -36z"/>
|
||||
<path d="M6364 6385 c25 -19 36 -19 36 0 0 10 -10 15 -27 15 -27 -1 -27 -1 -9
|
||||
-15z"/>
|
||||
<path d="M200 6381 c0 -5 -8 -8 -17 -7 -13 1 -19 -7 -21 -26 -5 -42 41 -35 50
|
||||
7 2 11 10 19 16 18 7 -2 12 2 12 7 0 6 -9 10 -20 10 -11 0 -20 -4 -20 -9z"/>
|
||||
<path d="M6245 6381 c-3 -5 -1 -12 5 -16 5 -3 10 -16 10 -28 1 -20 2 -21 14
|
||||
-4 7 9 16 17 20 17 3 0 6 -8 7 -17 0 -15 2 -15 9 2 5 11 9 29 9 40 0 19 0 19
|
||||
-10 2 -10 -17 -13 -17 -34 -3 -13 9 -26 12 -30 7z"/>
|
||||
<path d="M43 6320 c1 -20 8 -25 20 -14 7 8 -3 34 -13 34 -5 0 -8 -9 -7 -20z"/>
|
||||
<path d="M0 6290 c0 -14 6 -20 23 -19 16 1 17 3 5 6 -10 2 -15 10 -11 19 3 8
|
||||
0 14 -6 14 -6 0 -11 -9 -11 -20z"/>
|
||||
<path d="M6270 6289 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M338 6233 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
|
||||
<path d="M10 6213 c0 -13 5 -23 10 -23 13 0 13 11 0 30 -8 12 -10 11 -10 -7z"/>
|
||||
<path d="M40 6170 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0 -4
|
||||
-4 -4 -10z"/>
|
||||
<path d="M0 6149 c0 -5 5 -7 10 -4 5 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10 -5
|
||||
-10 -11z"/>
|
||||
<path d="M6310 6079 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M6375 6070 c4 -6 11 -8 16 -5 14 9 11 15 -7 15 -8 0 -12 -5 -9 -10z"/>
|
||||
<path d="M6271 5854 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M6040 5789 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M5070 5749 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M5240 5740 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
|
||||
-10 -4 -10 -10z"/>
|
||||
<path d="M3170 5705 c0 -11 11 -15 37 -15 35 0 36 1 17 15 -25 19 -54 19 -54
|
||||
0z"/>
|
||||
<path d="M3068 5693 c17 -2 47 -2 65 0 17 2 3 4 -33 4 -36 0 -50 -2 -32 -4z"/>
|
||||
<path d="M3285 5690 c22 -5 65 -9 95 -9 49 -1 264 -33 315 -47 11 -3 28 -8 38
|
||||
-10 9 -3 17 -1 17 4 0 18 -251 59 -405 66 -73 4 -89 3 -60 -4z"/>
|
||||
<path d="M2948 5683 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
|
||||
<path d="M3884 5589 c32 -11 63 -18 70 -16 13 5 -89 37 -113 36 -9 0 10 -9 43
|
||||
-20z"/>
|
||||
<path d="M2390 5570 c-9 -6 -10 -10 -3 -10 6 0 15 5 18 10 8 12 4 12 -15 0z"/>
|
||||
<path d="M3970 5566 c0 -2 9 -6 20 -9 11 -3 18 -1 14 4 -5 9 -34 13 -34 5z"/>
|
||||
<path d="M4030 5547 c0 -7 141 -59 146 -54 3 2 -27 16 -66 31 -72 26 -80 29
|
||||
-80 23z"/>
|
||||
<path d="M2290 5530 c-8 -5 -10 -10 -5 -10 6 0 17 5 25 10 8 5 11 10 5 10 -5
|
||||
0 -17 -5 -25 -10z"/>
|
||||
<path d="M4340 5399 c80 -45 173 -101 208 -125 35 -24 66 -44 70 -44 8 0 -60
|
||||
59 -69 60 -4 0 -37 21 -75 46 -65 43 -254 144 -271 144 -5 0 57 -37 137 -81z"/>
|
||||
<path d="M4700 5380 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
|
||||
-10 -4 -10 -10z"/>
|
||||
<path d="M1835 5290 c-3 -5 -2 -10 4 -10 6 0 50 -33 98 -73 48 -40 98 -80 110
|
||||
-88 12 -9 45 -36 73 -62 28 -26 56 -47 63 -47 7 0 6 -4 -3 -10 -13 -8 -13 -10
|
||||
1 -10 9 0 22 -7 29 -15 7 -8 16 -12 21 -9 5 3 -28 37 -73 77 -133 117 -144
|
||||
127 -125 121 9 -3 17 -1 17 5 0 6 -5 11 -10 11 -6 0 -20 9 -32 20 -12 11 -27
|
||||
20 -32 19 -6 0 -5 -3 2 -6 6 -2 12 -9 12 -15 0 -6 -6 -6 -15 2 -8 7 -15 18
|
||||
-15 26 0 7 -10 16 -22 20 -13 4 -34 17 -47 30 -25 25 -46 30 -56 14z"/>
|
||||
<path d="M4636 5216 c3 -9 14 -18 23 -21 10 -3 31 -18 47 -33 16 -15 38 -33
|
||||
49 -41 11 -7 -5 10 -35 38 -64 60 -93 79 -84 57z"/>
|
||||
<path d="M2065 5140 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
|
||||
-7 -4 -4 -10z"/>
|
||||
<path d="M2138 5087 c79 -71 202 -169 196 -155 -3 7 -39 40 -81 73 -41 33 -91
|
||||
75 -111 92 -20 18 -40 33 -44 33 -4 0 14 -19 40 -43z"/>
|
||||
<path d="M4780 5109 c0 -2 48 -51 107 -109 60 -58 96 -89 82 -70 -23 31 -189
|
||||
188 -189 179z"/>
|
||||
<path d="M2250 4951 c0 -5 5 -13 10 -16 6 -3 10 -2 10 4 0 5 -4 13 -10 16 -5
|
||||
3 -10 2 -10 -4z"/>
|
||||
<path d="M2375 4890 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
|
||||
-7 -4 -4 -10z"/>
|
||||
<path d="M2400 4873 c0 -5 13 -17 28 -27 l27 -19 -24 26 c-26 28 -31 32 -31
|
||||
20z"/>
|
||||
<path d="M2477 4809 c12 -12 24 -21 27 -18 2 2 -8 13 -22 23 l-27 19 22 -24z"/>
|
||||
<path d="M2495 4730 c10 -11 20 -20 23 -20 3 0 -3 9 -13 20 -10 11 -20 20 -23
|
||||
20 -3 0 3 -9 13 -20z"/>
|
||||
<path d="M1206 4694 c-5 -14 -4 -15 9 -4 17 14 19 20 6 20 -5 0 -12 -7 -15
|
||||
-16z"/>
|
||||
<path d="M2595 4628 c39 -39 82 -84 97 -99 15 -14 24 -29 21 -33 -3 -3 -1 -6
|
||||
5 -6 7 0 12 -4 12 -10 0 -5 -19 -11 -42 -12 -40 -1 -40 -1 -8 -5 19 -2 45 -6
|
||||
56 -8 22 -5 57 -49 57 -72 0 -7 4 -10 8 -7 11 6 56 -94 65 -146 11 -65 13
|
||||
-171 3 -197 -4 -12 -11 -44 -14 -70 -3 -26 -15 -81 -27 -120 -19 -65 -25 -73
|
||||
-47 -74 -14 -1 -30 -1 -35 0 -4 1 -14 -3 -21 -9 -12 -10 -71 -4 -90 10 -5 4
|
||||
-30 10 -55 13 -58 7 -80 16 -80 33 0 18 -37 36 -60 29 -10 -3 -33 1 -50 10
|
||||
-16 8 -30 11 -30 6 0 -13 47 -41 70 -41 11 0 20 -4 20 -10 0 -24 -85 -1 -106
|
||||
29 -9 12 -22 16 -43 13 -16 -2 -37 1 -48 8 -15 9 -13 10 16 6 l33 -6 -23 21
|
||||
-24 21 22 -5 c13 -3 26 -1 29 4 5 9 -15 13 -50 9 -10 -1 -15 3 -12 8 3 5 -6
|
||||
13 -22 17 -15 3 -41 17 -59 31 -17 13 -38 21 -46 18 -8 -3 -18 -1 -22 5 -3 6
|
||||
-16 11 -28 11 -22 0 -22 -1 3 -21 l25 -20 -32 15 c-78 39 -49 6 37 -40 38 -21
|
||||
68 -39 66 -41 -3 -3 -101 41 -126 57 -16 10 -284 99 -371 124 -30 8 -94 26
|
||||
-144 41 -107 31 -225 45 -208 23 6 -7 12 -16 12 -20 3 -22 114 -133 136 -136
|
||||
16 -2 14 2 -10 21 -55 45 -71 62 -78 80 -8 22 -6 22 130 -9 63 -14 120 -23
|
||||
126 -21 7 2 -19 11 -58 20 -96 23 -164 46 -139 46 34 1 343 -86 359 -101 11
|
||||
-11 -27 -3 -93 19 -24 8 -46 13 -48 11 -2 -3 56 -24 129 -48 72 -24 137 -46
|
||||
142 -50 6 -4 30 -15 55 -24 43 -16 158 -66 208 -89 12 -6 22 -15 22 -20 0 -10
|
||||
1 -11 -185 33 -71 17 -193 37 -270 46 -77 8 -154 19 -171 25 -17 5 -37 9 -46
|
||||
9 -17 0 -32 -26 -22 -41 3 -5 0 -9 -5 -9 -6 0 -11 5 -11 10 0 6 -4 10 -10 10
|
||||
-20 0 -9 -15 28 -40 46 -31 47 -32 100 -75 24 -19 49 -35 55 -35 19 1 -67 74
|
||||
-112 95 -53 26 -52 38 2 31 23 -3 85 -10 137 -16 52 -5 113 -12 135 -15 25 -3
|
||||
17 1 -20 9 -33 8 -107 20 -165 26 -130 14 -146 24 -25 15 203 -15 565 -91 550
|
||||
-116 -4 -5 -2 -9 4 -9 5 0 22 -5 38 -12 15 -6 34 -12 41 -14 45 -9 4 -12 -140
|
||||
-11 -197 2 -354 -7 -372 -23 -8 -6 -18 -10 -22 -9 -20 3 -34 -2 -34 -13 0 -6
|
||||
3 -8 7 -5 3 4 16 1 28 -7 18 -12 31 -12 86 0 l64 13 -70 -4 c-109 -8 -56 12
|
||||
70 26 122 13 313 6 348 -12 12 -7 33 -13 47 -15 14 -1 39 -9 55 -18 l30 -16
|
||||
-30 -1 c-73 -2 -172 -10 -190 -15 -11 -3 -71 -16 -133 -29 -61 -13 -120 -29
|
||||
-130 -35 -14 -8 -12 -9 11 -4 38 9 34 -3 -8 -20 -25 -11 -33 -19 -29 -30 5
|
||||
-13 -2 -16 -41 -16 -34 0 -44 -3 -39 -12 6 -10 4 -10 -8 0 -11 9 -17 10 -20 2
|
||||
-4 -12 -365 -23 -372 -11 -4 6 -260 -3 -346 -13 -25 -3 -71 -5 -104 -5 -51 -1
|
||||
-57 -3 -46 -16 7 -9 21 -13 31 -10 11 4 19 2 19 -4 0 -6 -4 -11 -10 -11 -14 0
|
||||
-13 -37 1 -46 12 -7 146 -35 164 -33 18 1 -29 18 -53 18 -13 1 -30 7 -38 15
|
||||
-7 8 -22 12 -33 9 -10 -3 -22 1 -27 8 -5 8 -3 11 8 7 8 -4 46 2 84 13 84 23
|
||||
243 38 469 44 94 2 197 7 230 10 49 4 55 3 35 -6 -14 -6 -41 -12 -60 -13 -20
|
||||
-1 -58 -10 -85 -19 -28 -9 -81 -23 -120 -33 -38 -9 -119 -30 -179 -46 -80 -21
|
||||
-111 -26 -117 -17 -4 6 -12 8 -18 5 -6 -4 -9 -11 -6 -15 2 -5 -16 -16 -40 -26
|
||||
-25 -9 -45 -22 -45 -29 0 -14 76 -43 87 -33 3 4 -1 7 -11 7 -39 0 1 21 97 50
|
||||
135 41 131 40 125 45 -2 2 -28 -2 -58 -10 -59 -16 -77 -18 -68 -10 3 3 52 17
|
||||
109 31 143 34 140 33 133 23 -3 -5 -15 -9 -27 -9 -12 0 -29 -5 -37 -10 -17
|
||||
-12 4 -8 100 16 52 13 300 54 418 69 31 4 56 13 59 21 3 8 13 14 22 14 9 0 23
|
||||
5 31 11 11 8 6 9 -22 5 -40 -5 -46 1 -25 23 10 11 9 13 -5 8 -9 -3 -41 -2 -70
|
||||
3 -31 4 -54 4 -56 -1 -4 -11 -22 -12 -22 -1 0 5 16 16 36 25 19 10 33 21 30
|
||||
25 -2 4 21 8 52 8 35 0 57 4 60 12 2 7 13 10 28 6 30 -8 96 4 89 16 -3 5 -1
|
||||
11 5 15 5 3 10 -1 10 -9 0 -10 9 -16 23 -16 15 0 18 3 9 9 -14 9 76 21 156 21
|
||||
34 0 43 -3 35 -11 -6 -6 -24 -11 -38 -11 -19 0 -23 -3 -14 -9 8 -5 11 -9 7
|
||||
-10 -8 -1 -19 -4 -35 -8 -5 -2 1 -6 11 -10 15 -6 4 -12 -45 -25 -77 -22 -205
|
||||
-73 -239 -97 -14 -9 -79 -27 -145 -39 -140 -26 -198 -43 -117 -35 83 9 61 -2
|
||||
-44 -20 -53 -10 -90 -21 -84 -25 13 -8 -99 -50 -134 -50 -18 0 -19 -2 -6 -11
|
||||
12 -9 10 -10 -8 -6 -13 3 -21 3 -18 0 3 -3 -25 -21 -62 -40 -72 -37 -104 -61
|
||||
-97 -73 7 -12 55 -18 61 -9 2 5 26 18 52 29 25 11 49 24 52 28 8 11 80 43 143
|
||||
63 64 20 100 38 79 39 -20 0 -240 -87 -291 -116 -50 -27 -69 -31 -51 -9 7 8
|
||||
16 15 21 15 5 0 49 19 97 41 93 44 276 109 301 108 9 0 -2 -9 -24 -19 -54 -25
|
||||
-34 -24 40 1 33 12 71 23 85 24 13 2 26 9 28 14 7 20 41 12 39 -9 -1 -22 -1
|
||||
-21 -34 -25 -50 -5 -114 -29 -137 -50 -14 -13 -27 -21 -30 -18 -6 6 -148 -70
|
||||
-196 -106 -57 -43 -59 -45 -45 -65 7 -9 15 -13 16 -8 6 15 149 104 239 149 91
|
||||
45 290 123 316 123 28 0 5 -17 -41 -30 -50 -14 -75 -35 -28 -24 l28 7 -22 -22
|
||||
c-12 -11 -24 -21 -27 -21 -3 0 -31 -16 -62 -34 -32 -19 -61 -33 -66 -30 -5 3
|
||||
-7 2 -6 -3 2 -4 -1 -9 -6 -10 -5 -1 -12 -6 -15 -11 -11 -18 -108 -72 -129 -72
|
||||
-11 0 -24 -4 -27 -10 -3 -6 4 -10 17 -10 23 -1 23 -1 -5 -23 l-27 -23 22 -21
|
||||
c20 -17 32 -20 86 -15 34 2 62 9 62 14 0 6 -7 8 -15 4 -17 -6 -75 3 -75 13 1
|
||||
3 24 23 53 44 140 101 160 117 166 123 9 10 -71 -36 -90 -53 -8 -7 -19 -13
|
||||
-23 -13 -10 0 -84 -58 -119 -93 -16 -16 -31 -26 -35 -23 -19 20 216 188 265
|
||||
190 18 1 35 5 40 9 4 5 0 5 -10 1 -37 -14 -15 15 26 34 68 32 80 36 115 37 38
|
||||
2 41 -6 10 -28 -19 -13 -20 -16 -6 -16 9 -1 20 4 23 9 3 6 11 10 18 10 14 0
|
||||
-17 -28 -87 -82 -74 -57 -216 -182 -216 -190 0 -5 7 -8 15 -8 8 0 15 -6 15
|
||||
-13 0 -15 77 -11 86 5 4 7 -9 8 -37 4 -33 -5 -39 -4 -21 4 12 5 22 14 22 20 0
|
||||
5 11 20 25 32 24 21 35 46 15 33 -5 -3 -10 -2 -10 3 0 6 7 13 16 16 8 3 12 2
|
||||
9 -4 -12 -20 12 -9 41 18 54 51 111 91 159 112 41 18 50 19 64 7 9 -8 22 -12
|
||||
29 -10 28 11 6 -15 -57 -67 -37 -30 -88 -78 -113 -107 -25 -28 -49 -49 -52
|
||||
-46 -3 4 -5 -6 -4 -21 2 -16 8 -30 14 -33 13 -5 158 37 151 44 -3 2 -26 -1
|
||||
-51 -8 -62 -15 -76 -3 -48 43 27 43 80 94 89 84 4 -3 -9 -21 -28 -39 -20 -18
|
||||
-42 -41 -49 -52 -8 -11 22 14 65 55 89 84 155 140 164 140 13 0 43 -43 34 -49
|
||||
-4 -3 -34 -39 -67 -78 -32 -40 -62 -73 -66 -73 -14 0 -41 -63 -32 -72 16 -16
|
||||
93 -5 137 19 12 7 25 7 40 -1 23 -12 118 -9 110 3 -2 4 -18 6 -35 3 -35 -5
|
||||
-39 10 -13 48 l17 25 -24 -20 -23 -20 13 25 c7 14 27 43 44 65 17 22 32 42 33
|
||||
44 2 2 6 1 10 -2 3 -4 -2 -17 -13 -30 -11 -12 -26 -31 -34 -42 -14 -18 -14
|
||||
-19 2 -7 9 8 22 11 27 7 7 -4 8 1 4 11 -5 13 -3 15 7 9 8 -5 11 -4 7 2 -4 6 2
|
||||
13 13 16 11 3 18 1 15 -3 -3 -5 -8 -28 -11 -52 -4 -24 -10 -51 -15 -60 -13
|
||||
-24 -11 -56 3 -60 7 -3 32 7 55 21 39 23 43 30 43 66 0 84 17 64 23 -27 4 -51
|
||||
9 -103 13 -116 5 -19 3 -21 -12 -16 -17 6 -17 5 1 -9 15 -11 22 -12 28 -4 5 7
|
||||
5 1 1 -13 -4 -14 -7 -29 -7 -35 1 -19 41 -200 58 -260 29 -101 34 -137 35
|
||||
-234 0 -107 -7 -126 -106 -275 -32 -49 -63 -96 -69 -105 -5 -9 -20 -31 -32
|
||||
-48 -13 -17 -23 -34 -23 -37 0 -8 -63 -101 -72 -104 -4 -2 -8 -9 -8 -16 0 -6
|
||||
-9 -18 -20 -26 -11 -8 -20 -19 -20 -25 0 -5 -19 -28 -43 -50 -23 -22 -40 -41
|
||||
-37 -42 3 -1 -5 -15 -18 -32 -13 -18 -27 -29 -32 -26 -6 3 -7 -1 -4 -9 3 -8
|
||||
-4 -25 -16 -38 -12 -13 -43 -54 -68 -93 -26 -38 -49 -72 -52 -75 -3 -3 -5 -16
|
||||
-6 -30 0 -14 -4 -50 -7 -80 -3 -30 -3 -85 0 -122 6 -67 6 -68 32 -62 38 8 100
|
||||
35 144 62 48 29 69 26 72 -13 4 -51 16 -129 20 -134 7 -6 85 34 143 72 28 20
|
||||
53 33 53 29 1 -4 2 -18 3 -32 5 -63 18 -120 29 -127 19 -12 115 -10 110 3 -2
|
||||
6 6 18 19 26 13 9 37 27 53 42 17 14 35 26 41 26 6 0 18 15 25 33 7 17 20 37
|
||||
29 44 8 6 11 15 7 19 -4 5 -12 2 -16 -5 -7 -10 -10 -11 -16 0 -5 8 1 20 16 32
|
||||
13 11 23 27 22 36 -2 9 3 6 9 -7 9 -19 9 -25 -3 -32 -11 -7 -11 -12 -1 -22 9
|
||||
-9 12 -9 12 2 0 25 22 -6 42 -57 25 -65 23 -104 -6 -138 l-24 -27 -18 31 c-10
|
||||
17 -21 31 -25 31 -4 0 -10 11 -13 25 -4 14 -11 25 -16 25 -6 0 -10 -2 -10 -5
|
||||
0 -11 24 -55 30 -55 4 0 12 -12 18 -26 7 -14 8 -23 3 -19 -5 3 -12 1 -15 -3
|
||||
-3 -5 -27 -6 -53 -2 -26 5 -53 4 -58 0 -6 -5 -35 -10 -65 -13 -45 -3 41 -7
|
||||
210 -9 51 -1 61 3 71 29 7 19 13 23 21 15 8 -8 8 -15 0 -25 -10 -11 -6 -14 22
|
||||
-15 32 -1 33 0 45 53 11 50 29 81 32 56 3 -21 4 -26 17 -56 7 -17 21 -36 30
|
||||
-42 23 -14 114 -25 128 -16 14 10 27 73 15 73 -5 0 -7 10 -5 23 4 22 2 19 -23
|
||||
-43 -14 -33 -15 -34 -29 -16 -8 11 -14 16 -14 10 0 -5 -5 -1 -11 8 -7 14 -2
|
||||
35 25 90 19 40 40 92 47 115 11 37 14 41 24 26 7 -10 11 -23 8 -30 -3 -6 2
|
||||
-22 11 -35 20 -28 20 -14 1 76 -13 60 -13 76 -1 116 8 25 12 58 11 74 -2 17 4
|
||||
35 16 47 10 10 14 19 9 19 -6 0 -9 28 -8 70 2 38 6 70 10 70 4 0 30 -48 58
|
||||
-107 28 -60 57 -119 64 -133 7 -14 21 -54 31 -88 10 -34 23 -62 28 -62 5 0 7
|
||||
6 5 13 -3 6 -13 39 -23 72 -10 33 -21 62 -25 65 -20 17 -100 223 -100 257 0
|
||||
18 -4 33 -9 33 -12 0 -20 80 -11 126 l7 39 26 -55 c34 -70 35 -39 2 34 -39 86
|
||||
-31 136 15 96 13 -11 19 -20 14 -20 -5 0 -2 -6 8 -13 9 -7 24 -27 35 -43 10
|
||||
-17 34 -55 53 -85 19 -30 42 -67 50 -84 8 -16 18 -32 21 -35 3 -3 23 -36 44
|
||||
-75 21 -38 43 -79 49 -90 37 -67 96 -143 96 -124 0 7 -7 20 -15 29 -8 9 -38
|
||||
61 -65 115 -28 54 -60 109 -70 123 -11 13 -20 31 -20 38 0 8 -5 14 -10 14 -6
|
||||
0 -16 12 -22 28 -7 15 -24 45 -39 67 -14 22 -34 58 -45 80 -10 22 -21 42 -24
|
||||
45 -22 16 -58 103 -62 148 l-5 52 23 -25 c12 -13 31 -38 41 -55 12 -20 24 -30
|
||||
38 -28 18 3 21 -4 26 -57 3 -33 7 -48 9 -32 4 43 5 45 11 51 12 13 -3 54 -24
|
||||
65 -21 10 -21 11 3 5 l25 -7 -20 24 c-11 13 -26 30 -34 36 -9 8 -10 13 -3 13
|
||||
6 0 -1 12 -15 26 -19 19 -23 28 -14 37 8 8 14 8 24 -2 10 -10 8 -11 -7 -5 -32
|
||||
12 -10 -12 24 -26 16 -7 27 -17 24 -22 -3 -5 2 -16 12 -23 15 -11 16 -14 4
|
||||
-15 -11 0 -11 -3 3 -11 11 -6 26 -12 35 -13 10 -2 28 -22 40 -45 l24 -41 -29
|
||||
12 c-15 6 -32 15 -38 20 -15 13 -27 9 -13 -5 15 -15 75 -41 82 -36 2 2 15 -9
|
||||
27 -26 13 -16 27 -31 31 -33 5 -2 8 -12 8 -23 0 -10 4 -19 9 -19 8 0 89 -103
|
||||
152 -195 46 -66 44 -64 85 -110 35 -38 36 -38 18 -8 -10 18 -30 47 -45 64 -15
|
||||
18 -33 44 -40 58 -8 14 -30 50 -51 79 -22 32 -34 60 -31 69 4 10 2 14 -5 9 -6
|
||||
-3 -13 -2 -17 4 -3 5 2 10 12 11 14 0 14 2 -4 9 -13 5 -23 16 -23 25 0 8 -4
|
||||
15 -10 15 -5 0 -7 7 -4 15 4 10 0 15 -11 15 -9 0 -14 4 -10 9 3 6 -3 14 -12
|
||||
20 -10 6 -13 11 -8 11 6 0 1 8 -11 18 -11 9 -46 54 -78 98 -31 45 -75 100 -96
|
||||
122 -25 26 -35 42 -27 45 7 3 4 6 -7 6 -12 1 -16 6 -12 16 3 9 0 15 -9 15 -8
|
||||
0 -15 6 -15 14 0 8 -6 17 -12 19 -10 4 -10 8 1 15 11 8 9 11 -10 14 -18 2 -27
|
||||
13 -37 43 -17 52 -17 191 0 220 3 6 18 62 32 125 15 63 31 131 36 150 5 19 12
|
||||
53 16 75 3 22 9 42 13 45 12 10 14 140 1 140 -6 0 -8 -5 -4 -11 8 -14 -27
|
||||
-189 -39 -189 -5 0 -7 -7 -3 -15 3 -8 -1 -21 -9 -29 -8 -7 -11 -17 -7 -20 3
|
||||
-4 2 -10 -3 -14 -9 -7 -55 -89 -55 -99 0 -2 4 -2 9 1 14 9 22 -23 11 -44 -7
|
||||
-13 -6 -20 3 -24 9 -5 9 -7 0 -12 -7 -3 -10 -11 -7 -18 3 -7 -2 -25 -10 -42
|
||||
l-16 -29 3 32 c1 17 6 29 11 25 5 -3 6 2 3 12 -4 10 -7 22 -7 27 0 20 -30 7
|
||||
-36 -16 -3 -14 -12 -25 -20 -25 -10 0 -14 -14 -15 -42 -2 -32 -3 -36 -6 -15
|
||||
-4 27 -5 28 -18 10 -13 -17 -14 -17 -28 2 -15 19 -16 18 -37 -17 -24 -41 -53
|
||||
-56 -75 -38 -24 20 -26 -7 -4 -46 15 -28 19 -46 14 -72 -4 -20 -2 -38 3 -41
|
||||
15 -9 3 -61 -13 -55 -7 3 -15 -5 -18 -17 -6 -21 -4 -21 60 -16 36 3 61 2 55
|
||||
-2 -10 -6 -13 -16 -21 -61 -1 -3 -5 1 -9 8 -6 9 -13 0 -22 -27 -13 -40 -74
|
||||
-110 -86 -99 -3 4 -15 -3 -27 -15 -20 -20 -21 -20 -27 -1 -4 10 -13 19 -21 19
|
||||
-7 0 -16 11 -19 24 -7 32 -30 40 -24 9 3 -14 -1 -11 -10 10 -9 18 -20 31 -26
|
||||
27 -5 -3 -10 3 -10 13 0 11 -6 22 -14 25 -11 4 -14 28 -7 58 0 3 18 4 39 3 20
|
||||
0 57 2 82 6 40 7 41 8 11 9 -24 1 -32 5 -28 15 3 8 -2 16 -15 19 -13 4 -19 13
|
||||
-17 29 1 13 -2 32 -7 43 -10 25 -10 82 1 113 7 22 6 23 -29 17 -29 -6 -36 -4
|
||||
-36 9 0 9 -3 16 -7 16 -5 0 -16 17 -26 38 -23 48 -48 52 -41 8 l4 -31 -9 28
|
||||
c-6 16 -7 36 -4 44 5 13 2 15 -15 11 -13 -4 -22 -1 -22 5 0 8 -3 7 -9 -1 -6
|
||||
-10 -10 -9 -14 7 -3 12 -20 28 -39 36 -18 8 -27 14 -19 15 11 0 10 4 -4 20
|
||||
-12 13 -15 27 -11 47 5 21 4 24 -4 13 -8 -12 -10 -11 -10 6 0 12 -7 27 -15 34
|
||||
-18 15 -20 70 -2 70 7 0 8 3 2 8 -5 4 -11 14 -12 22 -1 8 -12 48 -24 89 -22
|
||||
78 -18 94 22 84 11 -3 19 0 19 6 0 8 -12 11 -32 9 -33 -3 -33 -3 -38 49 -6 53
|
||||
-13 68 -33 68 -7 0 -11 10 -9 22 2 12 -1 24 -7 27 -12 8 16 96 31 96 5 0 6
|
||||
-10 3 -22 -5 -18 -4 -19 4 -8 15 22 24 5 11 -20 -8 -15 -8 -20 -1 -16 7 5 11
|
||||
-4 11 -26 0 -35 15 -67 25 -56 4 3 1 16 -5 28 -6 11 -9 31 -7 43 4 18 5 17 6
|
||||
-5 0 -16 6 -28 11 -28 6 0 10 -6 10 -12 0 -7 12 -24 27 -38 l26 -25 -6 25 c-4
|
||||
14 -7 33 -7 43 0 10 -8 17 -21 17 -17 0 -20 5 -17 40 2 22 7 39 12 38 14 -4
|
||||
27 55 16 66 -6 6 -10 17 -9 26 0 12 2 12 6 1 6 -15 44 -55 47 -49 20 36 24 74
|
||||
11 105 -20 47 -20 70 -1 54 10 -8 16 -9 21 -1 3 6 9 8 13 6 4 -2 7 9 8 25 1
|
||||
25 -1 27 -14 17 -12 -11 -14 -6 -8 37 7 64 10 78 20 93 4 6 2 12 -3 12 -6 0
|
||||
-11 13 -11 29 0 24 6 31 32 40 22 8 34 8 36 1 2 -5 11 -10 20 -9 11 0 12 3 5
|
||||
6 -9 3 -10 10 -3 23 7 12 7 28 0 44 -6 18 -6 26 1 26 6 0 7 5 3 11 -4 8 1 9
|
||||
16 4 20 -6 21 -4 18 27 l-3 33 47 -3 48 -3 -17 30 c-14 24 -20 27 -32 18 -12
|
||||
-10 -13 -9 -7 1 6 10 2 13 -15 10 -13 -1 -29 -14 -36 -28 -7 -14 -13 -18 -13
|
||||
-10 0 13 -1 13 -10 0 -10 -15 -12 -12 -13 28 -1 9 4 16 11 15 7 -2 12 4 12 12
|
||||
0 10 10 13 35 11 30 -2 35 1 35 19 0 13 -10 27 -25 35 -30 16 -32 33 -4 61 19
|
||||
19 20 21 3 33 -12 9 -14 15 -6 20 7 4 12 13 12 19 0 7 -4 6 -10 -3 -7 -11 -8
|
||||
-7 -4 15 3 20 -3 50 -21 90 l-25 60 24 -28 c14 -15 30 -44 35 -65 6 -21 17
|
||||
-46 25 -57 9 -11 16 -27 16 -36 0 -9 7 -20 16 -23 24 -9 26 -8 14 14 -17 32 7
|
||||
24 26 -10 23 -37 44 -47 44 -19 0 18 6 16 48 -19 67 -56 127 -78 172 -62 3 1
|
||||
25 1 50 1 l45 -2 -55 28 c-48 24 -55 32 -55 55 1 19 -2 25 -9 18 -6 -6 -42
|
||||
-10 -81 -9 l-70 1 58 12 c33 6 56 14 52 18 -14 14 17 38 47 38 27 0 30 3 24
|
||||
23 -3 12 -6 25 -6 29 0 9 -74 48 -90 48 -5 0 -10 -7 -10 -15 0 -18 3 -17 -37
|
||||
-6 -22 6 -42 6 -62 -2 l-29 -11 13 -43 c7 -24 19 -50 25 -58 7 -9 8 -15 2 -15
|
||||
-5 0 -15 6 -21 14 -21 26 -49 142 -32 131 5 -3 30 -2 57 2 39 5 44 8 26 14
|
||||
-13 5 -25 15 -28 24 -4 8 -13 15 -21 15 -7 0 -25 11 -39 25 -14 14 -35 27 -47
|
||||
29 -11 1 -23 8 -25 14 -2 6 -15 10 -30 8 -15 -2 -20 -1 -10 1 26 7 30 31 4 26
|
||||
-13 -3 -28 2 -35 11 -11 14 -11 16 5 17 11 0 14 3 7 6 -7 2 -13 9 -13 14 0 12
|
||||
67 12 75 -1 3 -5 25 -10 48 -10 31 0 38 3 27 10 -8 5 -27 10 -42 10 -16 0 -28
|
||||
4 -28 10 0 5 19 8 45 6 24 -3 47 0 50 5 4 5 16 10 28 11 30 2 -111 18 -148 16
|
||||
-63 -2 -135 9 -135 21 0 3 -14 12 -31 20 -17 7 -68 41 -113 75 -95 72 -124 90
|
||||
-80 50 54 -49 78 -69 137 -113 31 -23 57 -45 57 -50 0 -16 -55 -20 -77 -5 -22
|
||||
14 -82 64 -173 146 -82 73 -88 78 -96 78 -5 0 23 -32 61 -72z m311 -195 c15
|
||||
-20 18 -43 6 -43 -4 0 -23 13 -42 30 l-35 29 29 1 c16 0 35 -8 42 -17z m420
|
||||
-245 c10 -12 15 -19 9 -16 -5 3 -18 8 -28 11 -10 4 -15 11 -12 17 8 13 9 13
|
||||
31 -12z m-59 -33 c9 -25 -2 -27 -28 -6 l-24 20 23 1 c12 0 25 -7 29 -15z
|
||||
m-1348 -175 c85 -31 141 -57 141 -65 0 -5 -50 13 -180 64 -99 39 -67 40 39 1z
|
||||
m1461 10 c13 -8 13 -10 -2 -10 -9 0 -20 5 -23 10 -8 13 5 13 25 0z m-1180 -85
|
||||
c7 -8 9 -15 6 -15 -4 0 -14 7 -22 15 -9 8 -11 15 -6 15 5 0 15 -7 22 -15z m20
|
||||
-45 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z
|
||||
m48 -54 c11 -4 28 -4 38 -1 14 4 13 2 -3 -6 -12 -6 -33 -9 -47 -5 -20 5 -26
|
||||
12 -25 34 0 25 1 26 9 5 5 -12 17 -24 28 -27z m212 12 c0 -6 -6 -5 -15 2 -8 7
|
||||
-15 14 -15 16 0 2 7 1 15 -2 8 -4 15 -11 15 -16z m431 2 c22 -12 23 -19 10
|
||||
-54 -8 -18 -15 -23 -30 -19 -24 6 -29 33 -6 33 17 0 20 16 5 25 -11 7 -14 25
|
||||
-4 25 3 0 14 -5 25 -10z m-429 -47 c21 -9 35 -19 33 -23 -3 -4 15 -11 40 -14
|
||||
43 -7 62 -29 33 -39 -7 -2 1 -2 17 1 37 5 23 -13 -17 -23 -22 -6 -28 -4 -28
|
||||
10 0 11 -6 15 -17 12 -23 -5 -75 21 -68 33 4 6 -5 10 -20 10 -14 0 -28 6 -31
|
||||
14 -3 8 -16 17 -30 20 -13 4 -24 11 -24 17 0 13 63 3 112 -18z m-255 1 c-3 -3
|
||||
-12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m368 -14 c3 -5 1 -10 -4 -10
|
||||
-6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m-188 -36 c-3 -3 -12 -4
|
||||
-19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m49 -15 c3 -6 20 -17 38 -25 17 -7 24
|
||||
-13 16 -14 -8 0 -33 11 -55 25 -23 14 -33 25 -23 25 9 0 20 -5 24 -11z m172
|
||||
-46 c-10 -2 -18 -11 -18 -19 0 -8 -7 -14 -15 -14 -15 0 -21 21 -8 33 3 4 18 6
|
||||
32 6 17 -1 20 -3 9 -6z m53 -43 c-24 -21 -41 -26 -41 -12 0 5 12 13 28 19 39
|
||||
15 40 15 13 -7z m-251 0 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4
|
||||
10 6 0 11 -4 11 -10z m310 3 c0 -17 -36 -43 -59 -43 -28 0 -21 12 21 35 27 15
|
||||
38 18 38 8z m126 -30 c-7 -7 -26 7 -26 19 0 6 6 6 15 -2 9 -7 13 -15 11 -17z
|
||||
m-748 10 c-10 -2 -28 -2 -40 0 -13 2 -5 4 17 4 22 1 32 -1 23 -4z m643 -20
|
||||
c-5 -18 -16 -29 -34 -34 -33 -9 -36 2 -4 16 12 6 23 16 23 23 2 20 4 22 13 22
|
||||
5 0 6 -12 2 -27z m-734 11 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13
|
||||
-5z m806 -29 c-3 -9 -8 -14 -10 -11 -3 3 -2 9 2 15 9 16 15 13 8 -4z m-243
|
||||
-15 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z
|
||||
m-243 -13 c-36 -11 -37 -13 -22 -32 12 -16 14 -17 9 -2 -6 17 7 22 48 19 9 -1
|
||||
22 5 28 13 7 8 20 15 29 14 11 0 10 -3 -6 -11 -13 -6 -23 -15 -23 -20 0 -4 -7
|
||||
-8 -17 -8 -9 0 -13 -3 -10 -7 7 -6 -23 -27 -55 -39 -10 -3 -18 -10 -18 -15 0
|
||||
-13 2 -12 54 17 57 32 75 24 20 -8 l-39 -23 29 -5 c16 -3 31 -12 33 -20 4 -13
|
||||
3 -13 -7 0 -8 11 -13 12 -16 3 -3 -7 -12 -9 -21 -6 -10 4 -14 2 -9 -5 3 -6 2
|
||||
-13 -3 -16 -5 -4 -12 -2 -16 4 -4 6 -16 5 -35 -5 -35 -18 -44 -19 -34 -3 5 7
|
||||
2 9 -7 6 -45 -19 -49 -17 -15 6 28 18 48 23 68 19 35 -7 38 12 3 21 -14 4 -37
|
||||
0 -53 -7 -38 -20 -99 -30 -107 -18 -3 6 -26 8 -53 5 l-47 -5 40 20 c22 11 75
|
||||
32 118 47 43 15 76 28 75 30 -4 3 -147 -37 -183 -51 -16 -6 -17 -5 -9 4 14 15
|
||||
240 90 269 90 11 0 3 -6 -18 -12z m420 -36 c-22 -49 -40 -60 -30 -18 5 22 5
|
||||
22 -10 2 -13 -15 -16 -16 -17 -5 0 19 46 70 65 70 11 0 9 -11 -8 -49z m-77 23
|
||||
c0 -2 -7 -4 -15 -4 -8 0 -15 4 -15 10 0 5 7 7 15 4 8 -4 15 -8 15 -10z m-74
|
||||
-36 c-2 -18 -4 -40 -5 -48 -1 -12 -3 -12 -16 1 -12 12 -13 20 -3 47 16 41 29
|
||||
41 24 0z m177 -15 c-6 -40 -21 -44 -18 -5 4 52 5 56 14 47 5 -6 7 -25 4 -42z
|
||||
m-803 17 c0 -6 -27 -10 -62 -10 -45 0 -59 3 -48 10 20 13 110 13 110 0z m550
|
||||
-35 c-7 -8 -19 -15 -26 -15 -8 0 -14 -4 -14 -10 0 -5 -4 -10 -10 -10 -21 0 -9
|
||||
29 23 56 27 23 32 24 35 10 2 -9 -2 -23 -8 -31z m277 -2 c-3 -10 -5 -4 -5 12
|
||||
0 17 2 24 5 18 2 -7 2 -21 0 -30z m-337 23 c0 -2 -8 -10 -17 -17 -16 -13 -17
|
||||
-12 -4 4 13 16 21 21 21 13z m-400 -30 c0 -2 -7 -7 -16 -10 -8 -3 -12 -2 -9 4
|
||||
6 10 25 14 25 6z m721 -43 c4 -53 -8 -77 -30 -64 -18 12 -6 81 14 81 8 0 16
|
||||
-8 16 -17z m-326 -12 c-16 -10 -34 -16 -38 -14 -12 7 25 32 48 33 16 0 14 -4
|
||||
-10 -19z m125 2 c0 -10 -12 -24 -27 -30 -31 -15 -46 -7 -20 11 9 7 17 18 17
|
||||
25 0 6 7 11 15 11 8 0 15 -8 15 -17z m70 -9 c0 -8 -6 -14 -12 -14 -7 0 -4 -6
|
||||
7 -12 41 -23 46 -57 14 -89 -12 -12 -23 -31 -24 -43 -1 -12 -3 -27 -4 -34 0
|
||||
-7 -6 -10 -11 -7 -7 4 -7 12 0 24 5 10 7 21 4 24 -6 6 -6 77 0 117 3 14 5 33
|
||||
5 43 1 21 21 13 21 -9z m-161 -8 c-2 -2 -15 -7 -29 -10 l-25 -7 25 15 c21 12
|
||||
42 14 29 2z m-150 -25 c-41 -27 -146 -50 -133 -30 3 5 12 9 20 9 8 0 14 4 14
|
||||
9 0 8 95 38 129 40 8 1 -5 -12 -30 -28z m-365 -2 c-3 -5 -10 -7 -15 -3 -5 3
|
||||
-7 10 -3 15 3 5 10 7 15 3 5 -3 7 -10 3 -15z m456 7 c0 -2 -7 -7 -16 -10 -8
|
||||
-3 -12 -2 -9 4 6 10 25 14 25 6z m46 -23 c-11 -33 -146 -103 -146 -76 0 16 53
|
||||
59 90 73 19 7 39 17 44 21 14 12 19 4 12 -18z m80 -28 c-32 -25 -66 -38 -66
|
||||
-25 0 10 83 60 90 53 3 -3 -8 -15 -24 -28z m-1401 -19 c-23 -16 -65 -30 -65
|
||||
-22 0 6 59 34 75 35 5 1 1 -5 -10 -13z m1415 -11 c0 -8 -7 -15 -16 -15 -14 0
|
||||
-14 3 -4 15 7 8 14 15 16 15 2 0 4 -7 4 -15z m-285 -35 c-3 -5 -11 -10 -16
|
||||
-10 -6 0 -7 5 -4 10 3 6 11 10 16 10 6 0 7 -4 4 -10z m-112 -27 c-7 -2 -29
|
||||
-16 -49 -29 -20 -14 -39 -23 -41 -20 -3 3 16 19 43 35 26 17 50 28 53 25 3 -4
|
||||
1 -9 -6 -11z m157 13 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11
|
||||
6 0 10 -2 10 -4z m181 -33 c-12 -20 -14 -14 -5 12 4 9 9 14 11 11 3 -2 0 -13
|
||||
-6 -23z m-196 -21 c-39 -33 -95 -72 -95 -65 1 10 81 73 95 73 6 0 6 -3 0 -8z
|
||||
m-705 -12 c-8 -5 -19 -10 -25 -10 -5 0 -3 5 5 10 8 5 20 10 25 10 6 0 3 -5 -5
|
||||
-10z m965 -19 c-3 -6 -11 -11 -17 -11 -6 0 -6 6 2 15 14 17 26 13 15 -4z m-82
|
||||
-8 c-7 -3 -13 -9 -13 -15 0 -6 7 -7 16 -4 9 3 12 2 9 -5 -4 -6 -14 -8 -22 -5
|
||||
-11 4 -13 1 -8 -14 13 -42 -74 -120 -134 -120 -36 0 -38 4 -11 37 11 14 17 30
|
||||
13 37 -3 6 -3 8 1 5 4 -4 27 15 53 41 35 36 54 47 77 47 17 1 25 -1 19 -4z
|
||||
m-963 -23 c-14 -10 -27 -16 -30 -13 -6 6 30 33 44 33 6 0 0 -9 -14 -20z m1240
|
||||
0 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z
|
||||
m-810 -63 c0 -2 -14 -16 -32 -33 -30 -28 -30 -18 1 18 13 16 31 24 31 15z
|
||||
m647 -3 c-3 -4 0 -13 8 -21 24 -23 18 -59 -11 -78 -27 -17 -27 -17 -20 6 3 13
|
||||
8 35 11 49 5 24 5 24 -4 3 -6 -13 -12 -23 -15 -23 -2 0 -2 10 1 23 6 23 22 47
|
||||
31 47 3 0 3 -3 -1 -6z m120 -286 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4
|
||||
-12 1 -19z m723 -252 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11
|
||||
6 0 10 -2 10 -4z m-45 -149 c-4 -15 -13 -31 -21 -38 -8 -6 -14 -19 -14 -28 1
|
||||
-11 8 -7 25 14 14 17 25 25 25 19 0 -13 -39 -49 -61 -57 -24 -8 -43 37 -23 53
|
||||
8 7 14 18 14 26 0 11 50 44 58 38 2 -1 0 -13 -3 -27z m-493 14 c-10 -6 -7 -10
|
||||
12 -15 16 -4 26 -13 26 -24 0 -10 4 -22 9 -27 10 -11 3 -65 -8 -65 -14 1 -59
|
||||
48 -74 78 -14 30 -14 32 1 33 11 0 12 2 4 6 -18 7 -4 23 21 23 16 0 18 -3 9
|
||||
-9z m428 -30 c0 -6 -4 -13 -10 -16 -5 -3 -10 1 -10 9 0 9 5 16 10 16 6 0 10
|
||||
-4 10 -9z m-333 -43 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z
|
||||
m293 -48 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11
|
||||
-10z m56 -27 c-10 -10 -19 5 -10 18 6 11 8 11 12 0 2 -7 1 -15 -2 -18z m-386
|
||||
-35 c0 -6 7 -20 17 -30 9 -10 11 -18 5 -18 -6 0 -13 6 -15 13 -4 9 -7 9 -15
|
||||
-1 -6 -9 -9 -4 -10 17 0 17 4 31 9 31 5 0 9 -5 9 -12z m-203 -146 c-8 -9 -18
|
||||
-27 -21 -39 -4 -13 -13 -23 -19 -23 -7 -1 -1 -10 12 -21 l24 -20 -22 -42 c-13
|
||||
-23 -34 -63 -48 -89 -13 -26 -31 -52 -39 -59 -8 -6 -13 -26 -13 -43 2 -30 2
|
||||
-30 6 -3 2 15 9 25 14 22 5 -4 9 3 9 15 0 12 4 19 9 16 5 -4 12 7 16 24 4 17
|
||||
11 28 16 24 5 -3 9 4 9 16 0 11 7 23 15 26 8 4 13 10 10 14 -3 4 2 13 10 20 8
|
||||
7 15 20 15 29 0 14 2 14 10 1 14 -22 12 -59 -5 -76 -8 -9 -15 -23 -14 -32 0
|
||||
-12 3 -11 9 6 10 24 20 29 20 9 0 -21 -80 -138 -90 -132 -6 4 -10 -3 -10 -14
|
||||
0 -29 -18 -35 -23 -9 -2 13 -5 4 -7 -22 l-3 -45 -7 40 -7 40 -2 -53 c0 -33 -5
|
||||
-51 -11 -47 -5 3 -10 -3 -10 -14 0 -24 -16 -36 -23 -19 -3 7 -6 1 -6 -14 -1
|
||||
-42 -11 -60 -26 -48 -9 8 -14 1 -19 -30 -3 -22 -10 -40 -15 -40 -4 0 -22 -30
|
||||
-40 -67 -17 -38 -47 -95 -66 -128 -19 -33 -32 -67 -29 -76 7 -25 -41 -65 -114
|
||||
-94 -37 -15 -76 -32 -86 -37 -18 -10 -19 -6 -13 81 7 89 30 186 48 197 5 3 9
|
||||
22 9 42 0 26 3 33 11 25 8 -8 19 -3 40 18 16 15 29 33 29 39 0 11 76 122 109
|
||||
158 11 12 20 23 20 25 -5 15 66 125 138 211 18 21 30 42 28 47 -3 4 0 11 6 15
|
||||
8 4 9 3 5 -4 -5 -8 -1 -10 10 -5 11 4 13 8 6 11 -7 2 -12 8 -12 13 0 11 71
|
||||
113 82 117 5 2 8 10 8 17 0 8 6 20 13 27 8 7 20 25 28 38 l14 25 3 -23 c2 -13
|
||||
-3 -31 -11 -40z m3 -62 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10
|
||||
2 0 4 -4 4 -10z m130 -241 c0 -6 -4 -7 -10 -4 -5 3 -10 11 -10 16 0 6 5 7 10
|
||||
4 6 -3 10 -11 10 -16z m-100 -8 c0 -5 -6 -12 -12 -14 -8 -3 -6 -6 5 -6 19 -1
|
||||
24 -36 7 -46 -8 -5 -7 -11 0 -20 7 -8 14 -29 17 -47 8 -51 16 -49 11 4 -3 25
|
||||
-2 52 3 60 5 8 9 -11 9 -49 0 -36 -4 -63 -10 -63 -5 0 -10 -9 -10 -21 0 -11
|
||||
-6 -33 -14 -47 -16 -32 -29 -64 -46 -112 -12 -35 -17 -47 -65 -155 -14 -33
|
||||
-31 -72 -38 -87 -6 -16 -15 -28 -18 -28 -4 0 -16 -22 -28 -49 -17 -41 -31 -55
|
||||
-76 -81 -30 -17 -61 -30 -68 -27 -6 2 -17 -3 -24 -12 -10 -13 -12 12 -13 126
|
||||
0 154 2 159 59 183 21 8 28 16 22 24 -5 6 -9 16 -9 21 0 15 31 69 48 82 54 41
|
||||
55 43 38 37 -10 -3 -18 -1 -18 5 0 6 5 11 10 11 6 0 15 11 20 24 5 13 18 27
|
||||
29 31 12 3 18 12 15 20 -4 9 3 16 20 21 14 3 31 13 38 22 12 14 10 14 -10 3
|
||||
-27 -15 -40 -8 -24 12 11 13 76 48 117 62 11 4 15 9 8 12 -6 2 -30 -5 -52 -16
|
||||
-48 -25 -58 -26 -41 -6 7 8 18 15 25 15 7 0 23 9 36 21 l24 21 -28 -17 c-16
|
||||
-9 -31 -14 -34 -11 -6 5 56 46 71 46 5 0 7 3 4 6 -4 3 -16 0 -28 -6 -30 -16
|
||||
-32 -9 -10 28 19 30 40 43 40 23z m27 -23 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13
|
||||
3 -3 4 -12 1 -19z m560 0 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z
|
||||
m-517 -61 c0 -23 -4 -36 -10 -32 -6 3 -9 26 -8 51 2 54 18 37 18 -19z m537 21
|
||||
c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-53 -65 c1 -7 9 -20 17
|
||||
-30 26 -30 31 -53 11 -53 -16 -1 -16 -1 0 -11 14 -8 15 -15 8 -35 -6 -14 -8
|
||||
-29 -5 -34 3 -5 1 -11 -4 -14 -11 -7 -19 12 -16 44 1 14 -5 30 -14 37 -13 10
|
||||
-13 12 -1 13 10 0 11 3 3 11 -6 6 -9 18 -6 27 5 11 3 13 -7 7 -10 -6 -12 -2
|
||||
-8 18 3 15 1 28 -5 30 -6 2 -6 13 -2 27 l8 25 9 -25 c6 -14 11 -30 12 -37z
|
||||
m-452 -5 c-7 -7 -12 -8 -12 -2 0 14 12 26 19 19 2 -3 -1 -11 -7 -17z m-496
|
||||
-30 c-18 -26 -22 -17 -5 14 6 11 13 17 16 15 3 -3 -2 -16 -11 -29z m514 12
|
||||
c-8 -5 -19 -10 -25 -10 -5 0 -3 5 5 10 8 5 20 10 25 10 6 0 3 -5 -5 -10z m357
|
||||
-22 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-387 -8 c0 -5 -7
|
||||
-10 -16 -10 -8 0 -12 5 -9 10 3 6 10 10 16 10 5 0 9 -4 9 -10z m352 -35 c3
|
||||
-14 1 -25 -3 -25 -5 0 -9 -7 -9 -17 0 -9 -3 -13 -7 -9 -10 10 -11 56 -1 56 4
|
||||
0 4 7 1 17 -4 10 -2 14 4 10 6 -4 13 -18 15 -32z m82 -18 c-4 -20 -2 -27 3
|
||||
-19 7 9 13 -4 21 -39 9 -39 9 -55 1 -66 -7 -7 -9 -16 -6 -20 4 -3 2 -13 -3
|
||||
-22 -5 -10 -5 -23 -1 -30 6 -9 12 -3 20 20 6 18 13 30 16 27 3 -2 -4 -29 -14
|
||||
-59 -11 -30 -20 -48 -20 -41 -1 6 -1 14 -1 17 -1 3 -8 24 -17 47 -27 76 -33
|
||||
120 -21 175 12 56 31 64 22 10z m-425 7 c-12 -15 -11 -16 11 -10 21 6 22 5 8
|
||||
-4 -10 -6 -18 -22 -18 -35 0 -14 -4 -25 -10 -25 -5 0 -8 14 -6 30 2 17 -1 33
|
||||
-6 36 -5 3 -1 12 9 19 23 17 30 10 12 -11z m-558 -31 c-12 -20 -14 -14 -5 12
|
||||
4 9 9 14 11 11 3 -2 0 -13 -6 -23z m519 7 c0 -5 -7 -16 -16 -24 -9 -9 -11 -16
|
||||
-4 -16 6 0 8 -5 4 -12 -5 -8 -2 -9 10 -5 14 6 15 3 6 -13 -6 -11 -7 -20 -2
|
||||
-20 5 0 9 -17 10 -38 1 -22 13 -64 27 -96 27 -62 31 -81 14 -70 -8 4 -9 -3 -4
|
||||
-26 5 -25 4 -31 -5 -25 -8 5 -11 3 -8 -6 3 -8 -1 -36 -8 -64 -8 -27 -14 -62
|
||||
-14 -76 0 -20 -13 -36 -52 -66 -76 -58 -120 -81 -125 -66 -2 7 -11 9 -19 6 -8
|
||||
-3 -14 -2 -12 3 1 5 -3 25 -9 44 -6 19 -14 58 -17 87 -6 48 -3 59 45 155 28
|
||||
57 55 112 60 123 4 11 24 55 43 97 20 43 36 82 36 88 0 5 5 10 10 10 6 0 10 7
|
||||
10 16 0 8 5 12 10 9 6 -3 10 -10 10 -15z m186 -7 c-10 -10 -19 5 -10 18 6 11
|
||||
8 11 12 0 2 -7 1 -15 -2 -18z m131 5 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3
|
||||
4 -12 1 -19z m-61 -20 c4 -6 2 -14 -4 -16 -8 -2 -9 -9 -3 -20 11 -20 9 -72 -1
|
||||
-72 -5 0 -8 6 -9 13 -6 84 -6 107 1 107 5 0 12 -5 16 -12z m-246 -8 c0 -5 -5
|
||||
-10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m180 -46 c-7 -7
|
||||
-18 -14 -24 -14 -6 0 -3 7 7 14 9 7 17 18 17 24 0 6 -8 9 -17 6 -15 -5 -15 -3
|
||||
2 11 19 15 20 15 23 -5 2 -12 -2 -28 -8 -36z m208 13 c-2 -23 -6 -47 -9 -52
|
||||
-3 -6 -4 -20 -3 -32 0 -13 -3 -23 -7 -23 -12 0 -11 10 2 87 13 72 22 84 17 20z
|
||||
m-23 23 c3 -5 2 -10 -4 -10 -5 0 -13 5 -16 10 -3 6 -2 10 4 10 5 0 13 -4 16
|
||||
-10z m-932 -17 c-9 -26 -24 -43 -37 -43 -6 0 -3 7 7 14 9 7 17 21 17 30 0 9 4
|
||||
16 10 16 5 0 7 -8 3 -17z m657 -50 c0 -7 -4 -13 -10 -13 -5 0 -10 8 -10 18 0
|
||||
9 -3 28 -5 42 -5 22 -3 21 9 -5 9 -16 15 -36 16 -42z m-35 -13 c-4 -17 -3 -21
|
||||
3 -11 17 24 22 -5 12 -65 -6 -32 -10 -61 -10 -64 -1 -3 -9 16 -19 41 -15 38
|
||||
-19 81 -11 129 0 3 5 -2 10 -10 8 -13 10 -13 10 2 0 9 -5 20 -10 23 -6 4 -7
|
||||
11 -4 17 11 17 26 -33 19 -62z m281 28 c5 -13 7 -25 7 -28 -1 -3 -4 -36 -7
|
||||
-74 -3 -40 -11 -73 -18 -78 -10 -6 -10 -8 0 -8 17 0 15 -25 -3 -40 -9 -7 -13
|
||||
-21 -10 -31 5 -13 2 -17 -8 -14 -10 5 -12 25 -9 88 2 45 7 97 12 114 4 18 6
|
||||
42 3 54 -5 17 -3 20 7 14 10 -6 12 -4 7 8 -3 10 -2 17 3 17 5 0 12 -10 16 -22z
|
||||
m24 12 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11
|
||||
-10z m-135 -108 c4 -4 4 4 0 18 -4 14 -4 22 0 18 9 -9 14 -46 19 -147 2 -42 7
|
||||
-93 11 -113 4 -24 3 -38 -3 -38 -5 0 -10 6 -9 13 1 36 -4 57 -13 52 -6 -4 -7
|
||||
1 -3 11 3 10 2 15 -3 12 -5 -4 -10 12 -12 34 -1 22 -9 50 -17 62 -8 11 -15 27
|
||||
-15 36 0 13 1 13 10 0 6 -9 10 -10 10 -3 0 6 -7 19 -16 27 -14 15 -14 16 1 16
|
||||
9 0 14 4 10 10 -3 5 -2 22 2 37 l7 28 7 -33 c4 -18 10 -36 14 -40z m205 -1 c0
|
||||
-10 3 -21 7 -25 4 -4 8 -19 8 -34 0 -15 4 -33 9 -41 5 -8 4 -16 -4 -21 -9 -5
|
||||
-9 -9 -1 -14 6 -4 11 -12 11 -17 0 -6 -4 -8 -9 -5 -5 4 -7 -3 -4 -15 5 -18 3
|
||||
-20 -18 -15 -23 7 -23 6 -5 -8 17 -14 17 -19 6 -48 -28 -71 -71 -137 -85 -131
|
||||
-8 3 -15 -1 -15 -8 0 -7 -3 -10 -6 -6 -13 12 -11 73 3 95 7 12 11 27 8 32 -3
|
||||
6 -1 10 6 10 6 0 18 8 26 18 14 16 14 16 9 -1 -4 -11 -2 -16 5 -11 7 4 8 20 4
|
||||
41 -3 19 -2 33 2 30 5 -3 9 11 8 30 0 20 -6 38 -13 41 -6 2 -12 -1 -12 -8 0
|
||||
-6 5 -8 10 -5 6 3 10 1 10 -4 0 -6 -6 -11 -14 -11 -9 0 -12 -10 -9 -35 2 -25
|
||||
-2 -41 -17 -57 -15 -16 -20 -18 -20 -7 0 8 6 21 13 28 10 11 9 13 -5 8 -23 -8
|
||||
-23 7 -1 29 11 11 14 19 7 21 -15 5 -5 53 11 53 7 0 19 33 30 81 17 79 17 80
|
||||
31 54 8 -15 14 -35 14 -44z m-315 -61 c-10 -11 -21 -18 -23 -15 -3 3 3 12 14
|
||||
20 27 20 30 18 9 -5z m245 -4 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5
|
||||
11 10 11 6 0 10 -2 10 -4z m-236 -28 c-6 -20 -5 -21 9 -10 14 12 16 11 16 -5
|
||||
0 -10 3 -35 6 -55 4 -25 3 -38 -4 -38 -6 0 -11 -4 -11 -10 0 -5 7 -10 15 -10
|
||||
10 0 15 -10 15 -30 0 -30 15 -41 23 -17 3 9 7 9 20 -2 10 -7 17 -10 17 -5 0 4
|
||||
6 2 12 -4 10 -10 10 -15 -2 -22 -12 -7 -12 -12 -2 -22 16 -16 15 -59 -2 -92
|
||||
-11 -23 -15 -24 -20 -10 -8 21 2 56 15 49 5 -4 9 5 9 19 0 14 -4 26 -10 26 -5
|
||||
0 -10 -5 -10 -11 0 -6 -7 -17 -15 -25 -13 -13 -14 -12 -11 13 2 15 1 22 -1 16
|
||||
-7 -21 -23 -15 -23 8 0 11 -4 17 -10 14 -6 -3 -10 4 -10 16 0 12 -7 27 -16 34
|
||||
-9 6 -16 24 -16 38 0 15 -5 27 -11 27 -6 0 2 14 19 31 23 24 25 29 9 23 -18
|
||||
-7 -18 -6 -6 9 9 11 10 17 2 17 -6 0 -11 -4 -11 -10 0 -5 -4 -10 -9 -10 -5 0
|
||||
-7 10 -4 23 8 37 12 47 18 47 4 0 3 -10 -1 -22z m-24 -18 c0 -5 -5 -10 -11
|
||||
-10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m20 -49 c0 -5 -7 -11 -14
|
||||
-14 -10 -4 -13 -1 -9 9 6 15 23 19 23 5z m172 -56 c-6 -34 -12 -32 -12 6 0 16
|
||||
4 28 9 25 4 -3 6 -17 3 -31z m-82 5 c6 -11 8 -20 6 -20 -3 0 -10 9 -16 20 -6
|
||||
11 -8 20 -6 20 3 0 10 -9 16 -20z m102 -45 c-6 -32 -19 -42 -16 -12 1 12 3 25
|
||||
3 30 1 4 5 7 10 7 4 0 6 -11 3 -25z m78 -215 c0 -5 -12 -10 -26 -10 -14 0 -23
|
||||
4 -19 10 3 6 15 10 26 10 10 0 19 -4 19 -10z"/>
|
||||
<path d="M2275 3400 c-3 -5 -2 -10 4 -10 5 0 13 5 16 10 3 6 2 10 -4 10 -5 0
|
||||
-13 -4 -16 -10z"/>
|
||||
<path d="M2658 3315 c2 -14 8 -23 12 -20 10 6 1 45 -10 45 -4 0 -5 -11 -2 -25z"/>
|
||||
<path d="M2460 3115 c-8 -9 -8 -15 -2 -15 12 0 26 19 19 26 -2 2 -10 -2 -17
|
||||
-11z"/>
|
||||
<path d="M2763 1800 c0 -25 2 -35 4 -22 2 12 2 32 0 45 -2 12 -4 2 -4 -23z"/>
|
||||
<path d="M2732 1735 c0 -16 2 -22 5 -12 2 9 2 23 0 30 -3 6 -5 -1 -5 -18z"/>
|
||||
<path d="M2707 1719 c4 -13 8 -18 11 -10 2 7 -1 18 -6 23 -8 8 -9 4 -5 -13z"/>
|
||||
<path d="M2636 1673 c-6 -14 -5 -15 5 -6 7 7 10 15 7 18 -3 3 -9 -2 -12 -12z"/>
|
||||
<path d="M2611 1634 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M2543 1485 c0 -33 2 -45 4 -27 2 18 2 45 0 60 -2 15 -4 0 -4 -33z"/>
|
||||
<path d="M2511 1515 c1 -19 18 -51 18 -35 0 8 -4 22 -9 30 -5 8 -9 11 -9 5z"/>
|
||||
<path d="M2515 1427 c-4 -10 -5 -21 -1 -24 10 -10 18 4 13 24 -4 17 -4 17 -12
|
||||
0z"/>
|
||||
<path d="M2775 1580 c-16 -11 -25 -20 -19 -20 11 0 64 39 54 40 -3 0 -18 -9
|
||||
-35 -20z"/>
|
||||
<path d="M2811 1564 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M2610 1370 c-9 -6 -10 -10 -3 -10 6 0 15 5 18 10 8 12 4 12 -15 0z"/>
|
||||
<path d="M2819 1323 c-13 -16 -12 -17 4 -4 16 13 21 21 13 21 -2 0 -10 -8 -17
|
||||
-17z"/>
|
||||
<path d="M2789 1269 l-24 -20 28 17 c15 9 27 18 27 20 0 8 -8 4 -31 -17z"/>
|
||||
<path d="M2850 1235 c-1 -5 -2 -14 -1 -18 1 -4 -5 -15 -14 -23 -16 -16 -20
|
||||
-34 -7 -34 11 0 34 58 29 72 -3 7 -6 9 -7 3z"/>
|
||||
<path d="M2870 1221 c0 -6 4 -13 10 -16 6 -3 7 1 4 9 -7 18 -14 21 -14 7z"/>
|
||||
<path d="M2750 1140 c-9 -6 -10 -10 -3 -10 6 0 15 5 18 10 8 12 4 12 -15 0z"/>
|
||||
<path d="M2920 1313 c0 -4 5 -15 10 -23 8 -13 10 -13 10 2 0 9 -4 20 -10 23
|
||||
-5 3 -10 3 -10 -2z"/>
|
||||
<path d="M3206 1293 c-6 -14 -5 -15 5 -6 7 7 10 15 7 18 -3 3 -9 -2 -12 -12z"/>
|
||||
<path d="M3293 1275 c-12 -38 -5 -51 15 -29 8 8 9 14 2 14 -6 0 -8 10 -4 25 9
|
||||
38 -1 30 -13 -10z"/>
|
||||
<path d="M3270 1215 c0 -2 10 -10 23 -16 20 -11 21 -11 8 4 -13 16 -31 23 -31
|
||||
12z"/>
|
||||
<path d="M5160 4695 c0 -5 5 -17 10 -25 5 -8 10 -10 10 -5 0 6 -5 17 -10 25
|
||||
-5 8 -10 11 -10 5z"/>
|
||||
<path d="M2635 4680 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
|
||||
-7 -4 -4 -10z"/>
|
||||
<path d="M5732 4580 c0 -14 2 -19 5 -12 2 6 2 18 0 25 -3 6 -5 1 -5 -13z"/>
|
||||
<path d="M868 4410 c2 -45 5 -80 7 -78 1 1 5 31 8 66 2 35 7 65 10 68 13 13
|
||||
133 11 155 -3 13 -8 32 -11 44 -7 19 6 20 3 14 -26 -5 -30 -4 -31 11 -19 11
|
||||
10 14 10 9 2 -4 -8 -2 -13 6 -14 59 -3 116 -13 138 -23 14 -7 39 -16 55 -19
|
||||
17 -4 -6 11 -50 32 -44 22 -76 40 -72 40 10 1 176 -63 215 -83 45 -23 132 -56
|
||||
132 -50 0 3 -20 14 -45 25 -24 11 -47 24 -50 29 -3 6 -13 10 -22 10 -9 0 -41
|
||||
12 -72 26 -31 14 -65 30 -76 34 -11 4 -31 12 -45 18 -14 5 -34 14 -45 18 -14
|
||||
6 5 10 60 14 l80 6 -70 3 c-38 1 -144 4 -235 7 l-165 6 3 -82z m285 33 c-7 -2
|
||||
-19 -2 -25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z"/>
|
||||
<path d="M2076 4471 c-4 -5 -2 -12 3 -15 5 -4 12 -2 15 3 4 5 2 12 -3 15 -5 4
|
||||
-12 2 -15 -3z"/>
|
||||
<path d="M3388 4453 c34 -2 90 -2 125 0 34 2 6 3 -63 3 -69 0 -97 -1 -62 -3z"/>
|
||||
<path d="M4208 4453 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
|
||||
<path d="M4615 4450 c-96 -5 -86 -6 80 -7 108 -1 179 2 165 7 -28 9 -83 9
|
||||
-245 0z"/>
|
||||
<path d="M4937 4448 c-6 -4 43 -7 110 -5 76 1 113 5 100 10 -27 10 -192 6
|
||||
-210 -5z"/>
|
||||
<path d="M5200 4450 c0 -5 16 -10 35 -10 19 0 35 -4 35 -10 0 -5 -6 -10 -14
|
||||
-10 -7 0 -19 -6 -26 -14 -6 -8 -18 -12 -26 -9 -8 3 -20 0 -27 -5 -7 -6 -55
|
||||
-27 -107 -46 -52 -19 -90 -35 -84 -35 13 -1 101 27 131 41 13 6 26 8 29 5 4
|
||||
-4 -6 -11 -21 -17 -38 -15 -24 -25 16 -11 18 6 40 11 51 11 29 0 100 51 93 68
|
||||
-3 9 0 12 9 9 8 -3 20 1 26 9 7 8 19 14 28 14 8 0 13 2 10 5 -10 11 -158 15
|
||||
-158 5z m48 -75 c-3 -3 -25 -7 -49 -10 -33 -3 -38 -2 -19 4 28 10 76 14 68 6z"/>
|
||||
<path d="M5485 4449 c-16 -6 -17 -8 -3 -8 12 -1 18 -13 22 -43 12 -89 13 -91
|
||||
15 -21 0 39 -2 74 -6 76 -5 3 -17 1 -28 -4z"/>
|
||||
<path d="M3160 4390 c-8 -5 -12 -11 -9 -14 3 -3 14 1 25 9 21 16 8 20 -16 5z"/>
|
||||
<path d="M1088 4373 c12 -2 30 -2 40 0 9 3 -1 5 -23 4 -22 0 -30 -2 -17 -4z"/>
|
||||
<path d="M3315 4370 c3 -5 11 -10 16 -10 6 0 7 5 4 10 -3 6 -11 10 -16 10 -6
|
||||
0 -7 -4 -4 -10z"/>
|
||||
<path d="M3202 4339 c-7 -10 -8 -19 -3 -19 13 0 33 28 23 33 -4 3 -13 -3 -20
|
||||
-14z"/>
|
||||
<path d="M3275 4350 c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0
|
||||
-8 -4 -11 -10z"/>
|
||||
<path d="M1159 4341 c11 -7 10 -10 -5 -14 -18 -4 -18 -5 0 -6 12 -1 16 -6 12
|
||||
-16 -3 -10 1 -15 14 -15 10 0 36 -16 57 -35 42 -39 133 -95 154 -95 8 0 -18
|
||||
21 -56 47 -39 25 -92 68 -119 95 -27 26 -54 48 -60 48 -6 0 -5 -4 3 -9z"/>
|
||||
<path d="M1360 4344 c0 -6 65 -34 77 -34 9 1 -58 39 -69 40 -5 0 -8 -2 -8 -6z"/>
|
||||
<path d="M3275 4320 c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0
|
||||
-8 -4 -11 -10z"/>
|
||||
<path d="M3378 4323 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
|
||||
<path d="M871 4304 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M4991 4294 c-93 -35 -175 -74 -168 -80 3 -3 13 -1 24 4 28 16 83 39
|
||||
148 62 33 13 64 26 70 31 14 14 -3 10 -74 -17z"/>
|
||||
<path d="M1450 4304 c0 -7 126 -64 142 -64 7 1 -20 16 -61 35 -78 37 -81 38
|
||||
-81 29z"/>
|
||||
<path d="M3412 4298 c-18 -18 -14 -33 4 -17 14 11 18 10 30 -6 8 -11 13 -24
|
||||
11 -30 -2 -5 2 -16 10 -23 17 -18 17 -36 -1 -29 -10 4 -13 1 -9 -9 3 -7 11
|
||||
-14 19 -14 17 0 37 -37 30 -56 -3 -8 -2 -13 3 -10 17 11 29 -82 15 -118 -3 -9
|
||||
-12 -16 -20 -16 -8 0 -14 -7 -14 -15 0 -8 5 -15 10 -15 6 0 10 -23 10 -50 0
|
||||
-45 -4 -53 -39 -85 -36 -33 -39 -40 -45 -106 -4 -39 -5 -73 -2 -76 6 -6 42 27
|
||||
49 47 4 10 6 7 6 -8 1 -19 5 -21 27 -16 25 6 26 5 20 -20 -5 -20 -3 -26 9 -26
|
||||
9 0 13 -5 10 -10 -4 -6 -1 -18 6 -26 15 -18 25 -129 11 -120 -6 3 -4 -14 3
|
||||
-38 8 -24 10 -48 7 -52 -4 -4 -2 -4 4 -1 16 9 25 -18 11 -32 -8 -8 -8 -11 1
|
||||
-11 7 0 12 -7 12 -15 0 -8 -6 -15 -12 -15 -10 0 -9 -3 1 -9 7 -5 14 -20 14
|
||||
-35 0 -19 5 -26 19 -26 10 0 16 -4 13 -10 -3 -5 -2 -10 3 -10 10 0 32 -66 32
|
||||
-96 0 -16 -2 -16 -14 -4 -8 8 -17 28 -20 44 -8 44 -16 44 -16 0 0 -44 7 -57
|
||||
33 -67 10 -4 15 -11 12 -17 -8 -13 -35 -13 -35 0 0 6 -6 10 -14 10 -18 0 -27
|
||||
-36 -16 -63 9 -21 9 -21 7 3 -1 14 3 25 8 26 6 0 9 -7 7 -18 -2 -13 5 -20 27
|
||||
-24 17 -4 31 -11 31 -15 0 -5 14 -8 30 -7 22 2 30 7 30 21 0 14 5 17 18 13 11
|
||||
-4 8 1 -8 15 -14 12 -24 25 -23 30 2 5 -2 20 -7 35 -9 21 -7 29 7 40 17 13 17
|
||||
14 0 8 -13 -5 -16 -2 -11 10 3 9 11 16 18 16 12 0 36 -45 36 -67 0 -7 4 -13 8
|
||||
-13 9 0 57 -91 54 -102 -4 -16 19 -7 25 10 4 9 11 20 17 24 7 5 5 8 -5 8 -25
|
||||
0 -55 40 -79 105 -12 33 -32 74 -46 92 -14 19 -24 45 -24 65 0 19 -5 39 -12
|
||||
46 -9 9 -9 12 -1 12 7 0 15 -4 18 -10 11 -18 26 -10 20 10 -3 11 -4 20 0 20 6
|
||||
0 24 -44 30 -72 2 -9 9 -26 15 -38 6 -12 11 -38 10 -58 -3 -55 -1 -64 10 -57
|
||||
6 3 10 -1 10 -9 0 -9 4 -16 8 -16 17 0 21 13 11 31 -6 12 -6 26 -1 35 7 13 12
|
||||
11 27 -13 10 -15 24 -34 31 -40 7 -7 27 -39 45 -70 18 -31 34 -52 37 -45 2 7
|
||||
10 12 17 12 8 0 -7 31 -36 74 -27 42 -46 81 -43 89 3 8 1 18 -5 22 -7 4 -8 -1
|
||||
-4 -12 6 -16 5 -16 -10 -4 -25 20 -21 0 8 -39 26 -35 28 -40 21 -40 -9 0 -96
|
||||
119 -96 131 0 6 9 0 21 -15 17 -22 24 -24 41 -15 17 9 23 8 31 -6 7 -13 11
|
||||
-14 17 -5 8 12 70 -57 125 -138 32 -49 84 -96 94 -86 3 4 1 9 -5 11 -7 2 -9
|
||||
14 -6 25 4 17 2 20 -12 15 -10 -4 -15 -3 -11 3 8 13 -65 117 -137 196 -29 32
|
||||
-45 55 -35 51 10 -4 30 -7 44 -7 18 0 24 -4 19 -15 -3 -10 1 -15 11 -15 9 0
|
||||
28 -10 42 -22 14 -13 20 -16 14 -8 -25 28 -12 33 16 6 16 -16 28 -33 27 -40
|
||||
-2 -6 -1 -8 1 -3 8 13 25 7 20 -7 -3 -7 0 -13 8 -12 12 1 150 -124 157 -143 2
|
||||
-5 32 -11 68 -15 50 -4 58 -3 35 4 -16 6 -39 12 -50 14 -11 3 -21 5 -22 7 -2
|
||||
1 -7 2 -12 3 -13 2 -261 238 -261 249 0 4 4 6 8 3 4 -2 14 0 22 5 12 8 12 9
|
||||
-3 7 -11 -2 -26 12 -44 41 l-26 45 29 -20 c16 -12 36 -24 44 -27 30 -14 90
|
||||
-53 117 -77 15 -13 33 -25 38 -25 24 -2 65 -30 61 -41 -3 -8 -1 -16 4 -19 4
|
||||
-3 10 0 12 6 2 6 15 2 31 -11 15 -12 24 -26 21 -32 -5 -7 -2 -8 5 -4 17 11 92
|
||||
-43 89 -63 -2 -10 3 -15 14 -13 9 1 25 -9 36 -23 29 -37 36 -30 9 9 -20 31
|
||||
-120 109 -257 202 -25 17 -63 43 -85 59 l-40 27 40 -5 c22 -4 34 -4 28 -1 -7
|
||||
3 -13 12 -13 20 0 8 -7 14 -17 14 -9 0 -13 3 -10 6 9 9 69 -16 91 -38 10 -11
|
||||
25 -17 34 -13 9 3 14 3 10 0 -3 -3 42 -31 100 -61 58 -30 120 -65 137 -78 46
|
||||
-34 64 -41 32 -12 -15 14 -23 26 -17 26 18 0 71 -43 60 -50 -5 -3 1 -12 13
|
||||
-19 20 -13 21 -13 8 2 -21 27 1 19 38 -13 18 -15 30 -33 26 -39 -3 -6 -11 -8
|
||||
-17 -5 -7 4 -8 2 -4 -4 9 -14 16 -15 36 -2 12 7 11 13 -10 35 -39 41 -186 138
|
||||
-288 189 -51 25 -92 52 -92 59 0 7 -19 20 -42 29 -39 15 -40 17 -15 17 29 1
|
||||
269 -76 346 -111 25 -11 77 -36 114 -55 38 -19 66 -30 63 -24 -4 5 -40 26 -81
|
||||
47 -41 21 -73 39 -71 41 6 7 255 -120 278 -141 15 -14 22 -16 31 -6 9 9 8 15
|
||||
-7 25 -10 8 -15 18 -12 24 5 7 -3 9 -21 5 -21 -4 -61 11 -167 65 -77 39 -146
|
||||
71 -153 71 -7 0 -13 7 -13 15 0 9 -9 15 -25 15 -14 0 -34 9 -45 20 -21 21 -46
|
||||
28 -34 8 4 -7 3 -8 -5 -4 -6 4 -9 11 -6 16 3 5 -5 11 -17 13 -15 3 -11 5 13 6
|
||||
19 0 58 -5 85 -13 27 -8 81 -19 119 -26 78 -12 336 -77 420 -105 14 -4 12 -2
|
||||
-5 9 -28 17 -23 20 13 7 60 -23 127 -39 127 -30 0 5 -7 9 -15 9 -8 0 -15 4
|
||||
-15 9 0 6 10 8 22 6 12 -3 25 -1 28 3 3 4 16 13 30 20 l25 11 -25 -5 c-43 -9
|
||||
-93 -9 -129 0 -27 7 -32 6 -25 -5 6 -11 5 -12 -7 -3 -8 7 -30 15 -49 19 -19 4
|
||||
-46 12 -60 18 -26 11 -36 14 -58 16 -7 0 -11 5 -8 10 3 4 -7 8 -22 8 -37 0
|
||||
-172 35 -172 45 0 4 7 8 16 8 8 0 12 5 8 11 -5 8 8 10 42 5 27 -3 108 -8 179
|
||||
-11 72 -3 166 -7 210 -9 l80 -5 -85 14 -85 14 80 -5 c44 -2 91 -6 105 -8 14
|
||||
-1 50 -6 80 -11 30 -4 61 -12 68 -17 8 -8 12 -6 12 5 0 20 -64 34 -205 43
|
||||
-106 6 -160 11 -160 14 0 1 -15 3 -33 5 -25 2 -32 -1 -28 -11 4 -11 -8 -14
|
||||
-62 -13 -44 0 -60 3 -47 8 11 5 26 6 33 4 6 -3 12 0 12 6 0 6 -18 11 -42 11
|
||||
-24 1 -130 5 -236 10 -169 8 -196 11 -208 27 -13 16 -14 17 -8 1 4 -12 1 -18
|
||||
-10 -18 -9 0 -16 8 -16 18 0 11 -17 28 -42 42 -36 20 -39 24 -22 31 19 7 19 8
|
||||
-1 10 -11 1 -27 2 -35 1 -13 -1 -158 45 -215 68 -11 5 -33 12 -50 16 -28 7
|
||||
-28 8 -7 12 15 2 22 9 18 18 -4 11 7 14 58 14 34 0 87 -4 117 -10 175 -31 242
|
||||
-41 247 -36 3 3 2 6 -2 6 -4 0 -60 9 -124 20 -64 11 -132 23 -151 26 -18 3
|
||||
-31 7 -29 10 8 7 280 -35 336 -52 61 -18 68 -27 15 -19 -27 4 -32 3 -18 -4 30
|
||||
-13 91 -25 82 -15 -4 4 3 14 15 21 13 7 16 13 8 12 -8 -1 -26 -1 -39 0 -20 1
|
||||
-21 3 -11 16 11 13 5 15 -41 15 -30 0 -92 7 -139 15 -47 8 -102 15 -122 15
|
||||
-20 0 -39 4 -43 10 -3 5 -12 7 -20 3 -8 -3 -15 -1 -15 5 0 6 -15 9 -32 8 -37
|
||||
-3 -96 18 -80 28 18 11 212 36 287 37 49 0 64 3 50 9 -19 8 -19 9 2 9 12 1 24
|
||||
-5 26 -11 4 -10 6 -10 6 0 1 9 35 12 135 12 140 0 194 -8 146 -21 -23 -6 -22
|
||||
-7 8 -8 20 -1 31 3 27 9 -3 6 -2 10 4 10 5 0 11 -5 13 -12 2 -6 9 -8 16 -4 6
|
||||
3 9 13 5 21 -4 13 -45 15 -255 15 -162 0 -256 -4 -270 -11 -11 -6 -18 -7 -14
|
||||
-1 3 6 -22 8 -67 5 -116 -6 -56 22 133 63 36 8 119 27 185 44 174 44 321 70
|
||||
390 70 54 0 61 3 72 25 11 24 10 25 -20 25 -29 0 -30 1 -11 15 25 19 11 19
|
||||
-27 -1 -17 -8 -36 -13 -42 -11 -7 2 -20 0 -30 -5 -20 -10 -140 -38 -317 -73
|
||||
-69 -13 -141 -29 -160 -34 -58 -16 -110 -22 -110 -11 0 5 20 21 45 36 25 14
|
||||
44 28 41 31 -2 2 -12 0 -23 -6 -10 -5 -52 -24 -93 -41 l-75 -30 50 5 50 5 -35
|
||||
-17 c-19 -10 -42 -26 -52 -35 -10 -10 -25 -18 -33 -18 -8 0 -15 -6 -15 -14 0
|
||||
-9 -7 -12 -18 -9 -13 3 -18 -2 -19 -18 -3 -31 -25 -52 -81 -73 -58 -23 -87
|
||||
-55 -44 -49 l27 3 -25 -11 c-14 -6 -33 -15 -42 -20 -10 -5 -35 -9 -55 -10 -33
|
||||
0 -35 -1 -15 -9 33 -14 27 -17 -28 -16 -51 2 -63 -6 -33 -22 12 -7 4 -9 -30
|
||||
-7 -57 4 -87 13 -87 27 0 5 7 8 15 4 8 -3 15 -1 15 3 0 5 -6 11 -12 14 -19 6
|
||||
43 35 89 43 25 4 40 11 40 20 0 24 -47 28 -122 9 -40 -10 -78 -15 -86 -12 -9
|
||||
4 -7 6 6 6 22 1 217 92 211 99 -8 8 -140 -42 -158 -60 -10 -10 -28 -18 -40
|
||||
-18 -23 1 -23 1 2 16 17 10 18 13 5 9 -41 -14 -105 -18 -105 -6 0 6 -6 11 -13
|
||||
11 -10 0 -14 17 -15 60 0 33 -3 64 -6 69 -4 5 0 11 6 13 9 3 13 31 12 99 -2
|
||||
123 -5 139 -27 151 -11 5 -16 16 -13 24 3 9 1 12 -4 9 -6 -3 -10 2 -10 12 -1
|
||||
15 -52 83 -63 83 -2 0 -8 -5 -15 -12z m1473 -256 c-12 -11 -109 -32 -138 -31
|
||||
-18 1 -16 3 8 10 17 5 53 13 80 18 28 5 52 9 55 10 2 0 0 -3 -5 -7z m68 1 c-7
|
||||
-2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z m-236 -39 c-3 -3 -12 -4
|
||||
-19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m-122 -29 c-49 -12 -108 -25 -130 -28
|
||||
-69 -11 -1 13 95 33 119 25 143 22 35 -5z m-1148 -267 c-3 -8 -6 -5 -6 6 -1
|
||||
11 2 17 5 13 3 -3 4 -12 1 -19z m746 15 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5
|
||||
14 0 19 -2 13 -5z m-746 -55 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1
|
||||
-19z m148 12 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11
|
||||
-10z m45 -28 c0 -13 -12 -22 -22 -16 -10 6 -1 24 13 24 5 0 9 -4 9 -8z m365
|
||||
-2 c3 -5 19 -10 34 -10 16 0 44 -6 62 -14 19 -7 45 -17 59 -20 l25 -7 -25 15
|
||||
c-14 9 -22 15 -19 16 18 1 183 -61 198 -74 10 -9 24 -16 32 -16 12 0 12 -2 0
|
||||
-9 -11 -7 -9 -10 8 -16 28 -9 22 -29 -10 -32 -53 -3 -292 36 -308 51 -10 9
|
||||
-20 16 -24 16 -5 0 -75 45 -85 55 -2 2 7 2 20 -1 12 -3 3 4 -21 14 -48 21 -42
|
||||
38 10 27 22 -5 29 -4 25 4 -4 6 -3 11 3 11 5 0 13 -4 16 -10z m96 -8 c-7 -2
|
||||
-18 1 -23 6 -8 8 -4 9 13 5 13 -4 18 -8 10 -11z m-501 -17 c13 -14 21 -28 17
|
||||
-31 -8 -8 -56 28 -57 44 0 19 14 14 40 -13z m115 -15 c5 -8 11 -8 20 0 10 8
|
||||
21 8 41 -3 l28 -14 -29 0 c-16 0 -32 -8 -38 -18 -8 -15 -11 -13 -25 14 -10 22
|
||||
-20 30 -31 26 -8 -3 -12 -3 -8 1 4 4 -1 13 -11 21 -12 10 -9 10 15 -1 17 -9
|
||||
35 -21 38 -26z m-115 -36 c12 -31 12 -34 2 -34 -4 0 -13 14 -19 30 -6 17 -7
|
||||
30 -2 30 5 0 14 -12 19 -26z m56 2 c20 -21 17 -28 -6 -16 -11 6 -20 15 -20 20
|
||||
0 14 9 12 26 -4z m290 -21 c-3 -8 2 -16 10 -19 10 -4 13 -1 9 7 -4 6 -1 5 7
|
||||
-3 7 -8 20 -16 28 -18 26 -6 81 -53 90 -77 5 -12 18 -25 29 -28 32 -8 25 -23
|
||||
-9 -21 -59 4 -130 26 -123 37 3 7 2 9 -2 4 -13 -11 -64 43 -58 62 4 14 3 14
|
||||
-6 1 -6 -8 -11 -12 -11 -7 0 18 -2 23 -16 30 -12 7 -12 10 1 23 8 8 20 12 27
|
||||
8 8 -5 9 -2 5 9 -4 11 -2 14 9 10 8 -3 13 -11 10 -18z m-59 9 c-3 -3 -12 -4
|
||||
-19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m-174 -21 c-7 -2 -19 -2 -25 0 -7 3
|
||||
-2 5 12 5 14 0 19 -2 13 -5z m-68 -13 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0
|
||||
6 2 10 4 10 3 0 8 -4 11 -10z m163 -72 c7 -16 8 -28 2 -28 -12 0 -35 36 -45
|
||||
69 -7 23 -7 24 12 5 10 -10 24 -31 31 -46z m156 -57 c-5 -5 -75 73 -87 98 -5
|
||||
9 14 -9 42 -39 27 -30 48 -56 45 -59z m-69 52 c27 -32 33 -44 20 -39 -11 5
|
||||
-28 9 -37 10 -9 0 -15 3 -13 6 2 3 -3 19 -11 35 -8 17 -12 22 -9 12 3 -10 1
|
||||
-15 -5 -12 -14 9 -12 35 3 35 6 -1 30 -22 52 -47z m-286 7 c7 -23 7 -29 -1
|
||||
-24 -7 5 -9 0 -6 -13 3 -12 2 -26 -2 -33 -5 -8 -10 -2 -14 16 -4 16 -3 30 2
|
||||
32 5 1 7 14 4 27 -6 35 4 31 17 -5z m606 20 c3 -5 27 -10 53 -11 26 0 63 -7
|
||||
82 -14 35 -14 35 -14 5 -11 -16 1 -37 6 -45 9 -8 4 -46 8 -84 9 -45 2 -71 7
|
||||
-74 16 -5 15 54 17 63 2z m618 -37 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0
|
||||
19 -2 13 -5z m-608 -21 c-3 -3 -11 0 -18 7 -9 10 -8 11 6 5 10 -3 15 -9 12
|
||||
-12z m240 8 c13 -6 5 -7 -25 -3 -25 3 -47 7 -49 9 -9 8 55 2 74 -6z m142 4
|
||||
c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m-802 -44 c10 -11 13
|
||||
-20 7 -20 -6 0 -16 9 -22 20 -6 11 -9 20 -7 20 2 0 12 -9 22 -20z m110 -1 c11
|
||||
-17 -1 -21 -15 -4 -8 9 -8 15 -2 15 6 0 14 -5 17 -11z m-192 -19 c3 -11 1 -18
|
||||
-4 -14 -5 3 -9 12 -9 20 0 20 7 17 13 -6z m502 10 c3 -5 1 -10 -4 -10 -6 0
|
||||
-11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m458 3 c-7 -2 -19 -2 -25 0 -7 3
|
||||
-2 5 12 5 14 0 19 -2 13 -5z m-548 -13 c3 -6 -1 -7 -9 -4 -18 7 -21 14 -7 14
|
||||
6 0 13 -4 16 -10z m705 -16 c30 -8 60 -16 65 -17 6 -1 24 -8 40 -14 17 -7 50
|
||||
-17 74 -23 23 -6 41 -14 38 -17 -3 -2 -50 9 -104 25 -54 17 -133 38 -175 47
|
||||
-43 9 -78 19 -78 22 0 7 74 -6 140 -23z m-1200 -47 c0 -16 -18 3 -23 25 -6 22
|
||||
-5 22 8 4 8 -11 15 -24 15 -29z m374 27 c3 -8 2 -12 -4 -9 -6 3 -10 10 -10 16
|
||||
0 14 7 11 14 -7z m-334 -30 c0 -8 -4 -12 -10 -9 -5 3 -10 13 -10 21 0 8 5 12
|
||||
10 9 6 -3 10 -13 10 -21z m170 -16 c0 -12 3 -19 6 -15 10 9 36 -21 29 -33 -4
|
||||
-7 -16 0 -30 16 -13 15 -22 31 -19 36 3 4 0 8 -6 8 -6 0 -8 5 -5 10 10 16 25
|
||||
2 25 -22z m155 2 c3 -5 2 -10 -4 -10 -5 0 -13 5 -16 10 -3 6 -2 10 4 10 5 0
|
||||
13 -4 16 -10z m-323 -35 c7 -32 -8 -54 -14 -23 -3 12 -9 31 -13 41 -5 13 -3
|
||||
16 8 11 8 -3 17 -16 19 -29z m948 25 c8 -5 11 -10 5 -10 -5 0 -17 5 -25 10 -8
|
||||
5 -10 10 -5 10 6 0 17 -5 25 -10z m550 -10 c13 -9 13 -10 0 -10 -8 0 -22 5
|
||||
-30 10 -13 9 -13 10 0 10 8 0 22 -5 30 -10z m-730 -30 c8 -5 11 -10 5 -10 -5
|
||||
0 -17 5 -25 10 -8 5 -10 10 -5 10 6 0 17 -5 25 -10z m-369 -162 c10 -20 24
|
||||
-38 31 -41 9 -4 9 -6 1 -6 -6 -1 -26 18 -45 41 -35 46 -57 72 -100 122 -15 17
|
||||
-28 36 -27 41 0 16 120 -117 140 -157z m476 96 c-5 -5 -77 35 -77 42 0 3 18
|
||||
-5 41 -16 23 -12 39 -24 36 -26z m-592 -125 c9 -16 12 -29 7 -29 -7 0 -20 20
|
||||
-40 64 -11 23 20 -9 33 -35z"/>
|
||||
<path d="M4220 3584 c56 -25 116 -46 105 -36 -13 11 -115 52 -129 52 -6 -1 5
|
||||
-8 24 -16z"/>
|
||||
<path d="M5180 4299 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M4916 4291 c-4 -5 3 -7 14 -4 23 6 26 13 6 13 -8 0 -17 -4 -20 -9z"/>
|
||||
<path d="M1560 4285 c0 -3 27 -17 59 -31 40 -18 58 -30 54 -40 -5 -13 39 -31
|
||||
66 -25 7 1 10 -2 6 -8 -4 -7 0 -8 11 -4 13 5 15 3 9 -7 -5 -8 -4 -11 3 -6 6 3
|
||||
17 0 24 -8 8 -7 25 -17 38 -21 14 -4 41 -18 60 -30 19 -12 41 -20 49 -17 8 3
|
||||
11 0 7 -6 -7 -11 21 -25 35 -16 5 3 8 0 7 -8 -2 -7 2 -12 9 -11 6 1 17 -4 23
|
||||
-12 13 -16 35 -21 26 -6 -3 5 6 11 21 14 20 4 55 -10 133 -50 113 -60 119 -62
|
||||
255 -98 121 -31 153 -44 136 -54 -9 -6 -3 -10 17 -14 16 -3 36 -13 44 -21 19
|
||||
-19 88 -32 88 -17 0 6 -9 11 -19 11 -11 0 -32 11 -48 24 -15 13 -46 29 -68 37
|
||||
-22 7 -44 16 -50 20 -5 4 -26 10 -45 14 -49 10 -129 34 -167 51 -17 8 -35 14
|
||||
-39 14 -16 0 -144 64 -144 72 0 4 -8 8 -17 8 -10 0 -27 7 -37 15 -11 8 -27 15
|
||||
-35 15 -14 0 -14 -1 -1 -10 13 -8 12 -10 -2 -10 -10 0 -18 5 -18 10 0 6 -9 10
|
||||
-20 10 -11 0 -118 50 -239 110 -214 108 -231 115 -231 105z m165 -85 c3 -5 -4
|
||||
-6 -15 -3 -11 3 -22 9 -25 13 -3 5 4 6 15 3 11 -3 22 -9 25 -13z"/>
|
||||
<path d="M4868 4273 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
|
||||
<path d="M5168 4273 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
|
||||
<path d="M869 4135 c-3 -66 -8 -129 -11 -140 -3 -11 -3 -14 -1 -7 3 6 8 12 13
|
||||
12 5 0 11 -6 13 -12 8 -18 6 114 -2 197 -7 69 -7 68 -12 -50z"/>
|
||||
<path d="M3260 4239 c0 -5 9 -9 19 -9 11 0 22 4 25 9 3 5 -6 9 -19 9 -14 0
|
||||
-25 -4 -25 -9z"/>
|
||||
<path d="M4725 4204 c-63 -31 -80 -43 -55 -38 19 3 42 12 51 20 8 8 18 14 21
|
||||
14 3 0 26 11 49 25 70 40 32 28 -66 -21z"/>
|
||||
<path d="M4785 4200 c-3 -5 -2 -10 4 -10 5 0 13 5 16 10 3 6 2 10 -4 10 -5 0
|
||||
-13 -4 -16 -10z"/>
|
||||
<path d="M4745 4180 c-3 -6 1 -7 9 -4 18 7 21 14 7 14 -6 0 -13 -4 -16 -10z"/>
|
||||
<path d="M4603 4150 c-13 -5 -23 -12 -23 -15 0 -9 16 -5 36 10 22 16 19 18
|
||||
-13 5z"/>
|
||||
<path d="M5023 4143 c9 -2 23 -2 30 0 6 3 -1 5 -18 5 -16 0 -22 -2 -12 -5z"/>
|
||||
<path d="M4980 4124 c-13 -15 -6 -17 24 -5 17 6 17 8 3 14 -8 3 -21 -1 -27 -9z"/>
|
||||
<path d="M5511 4114 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M4543 4113 c9 -2 14 -9 11 -15 -4 -7 -2 -8 5 -4 15 10 4 26 -17 25
|
||||
-15 -1 -15 -2 1 -6z"/>
|
||||
<path d="M4930 4100 c-9 -6 -10 -10 -3 -10 6 0 15 5 18 10 8 12 4 12 -15 0z"/>
|
||||
<path d="M3430 4087 c0 -8 7 -18 16 -21 11 -4 14 -1 12 11 -4 21 -28 30 -28
|
||||
10z"/>
|
||||
<path d="M4471 4081 c-31 -24 -11 -37 26 -17 16 8 22 15 15 16 -7 0 -10 5 -7
|
||||
10 10 16 -8 11 -34 -9z m29 -5 c0 -2 -7 -7 -16 -10 -8 -3 -12 -2 -9 4 6 10 25
|
||||
14 25 6z"/>
|
||||
<path d="M3493 4073 c-18 -7 -16 -33 2 -33 8 0 15 9 15 20 0 11 -1 20 -2 19
|
||||
-2 0 -9 -3 -15 -6z"/>
|
||||
<path d="M5506 4062 c-7 -11 1 -263 8 -270 3 -3 6 58 6 136 0 135 -2 153 -14
|
||||
134z"/>
|
||||
<path d="M1958 4034 c24 -14 46 -24 49 -21 5 6 -69 47 -84 47 -4 0 11 -12 35
|
||||
-26z"/>
|
||||
<path d="M4408 4049 c-10 -5 -18 -15 -18 -21 0 -9 3 -9 12 0 7 7 20 12 31 12
|
||||
10 0 15 5 12 10 -8 12 -15 12 -37 -1z"/>
|
||||
<path d="M3430 4038 c0 -4 -7 -5 -15 -2 -8 4 -15 1 -15 -6 0 -6 9 -14 20 -17
|
||||
11 -3 20 -9 20 -15 0 -5 8 -4 19 2 25 13 17 49 -10 47 -10 -1 -19 -5 -19 -9z"/>
|
||||
<path d="M3077 4033 c-12 -12 -7 -22 8 -17 8 4 15 10 15 15 0 11 -14 12 -23 2z"/>
|
||||
<path d="M2082 4014 c10 -10 20 -15 24 -12 3 4 -5 12 -18 18 -22 12 -22 12 -6
|
||||
-6z"/>
|
||||
<path d="M878 3925 c2 -19 6 -35 8 -35 2 0 4 16 4 35 0 19 -4 35 -8 35 -4 0
|
||||
-6 -16 -4 -35z"/>
|
||||
<path d="M4895 3950 c-3 -5 -2 -10 4 -10 5 0 13 5 16 10 3 6 2 10 -4 10 -5 0
|
||||
-13 -4 -16 -10z"/>
|
||||
<path d="M4790 3900 c-9 -6 -10 -10 -3 -10 6 0 15 5 18 10 8 12 4 12 -15 0z"/>
|
||||
<path d="M3960 3874 l-35 -14 35 6 c19 4 44 10 55 15 l20 8 -20 0 c-11 0 -36
|
||||
-7 -55 -15z"/>
|
||||
<path d="M1881 3836 c2 -2 27 -6 54 -9 34 -4 42 -3 25 3 -25 8 -87 13 -79 6z"/>
|
||||
<path d="M796 3798 c-3 -13 -5 -34 -5 -48 1 -15 5 -7 10 19 9 47 6 68 -5 29z"/>
|
||||
<path d="M3920 3800 c-8 -5 -12 -11 -10 -14 3 -2 14 2 24 10 22 15 10 19 -14
|
||||
4z"/>
|
||||
<path d="M3865 3770 c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0
|
||||
-8 -4 -11 -10z"/>
|
||||
<path d="M3950 3739 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M3387 3683 c-13 -28 -13 -33 -3 -18 9 11 20 25 26 32 12 15 13 23 2
|
||||
23 -5 0 -16 -17 -25 -37z"/>
|
||||
<path d="M772 3669 c-5 -19 -6 -38 -3 -44 3 -5 9 8 12 30 9 50 3 58 -9 14z"/>
|
||||
<path d="M2980 3690 c0 -6 7 -10 15 -10 8 0 15 2 15 4 0 2 -7 6 -15 10 -8 3
|
||||
-15 1 -15 -4z"/>
|
||||
<path d="M4110 3685 c0 -8 5 -15 10 -15 6 0 10 7 10 15 0 8 -4 15 -10 15 -5 0
|
||||
-10 -7 -10 -15z"/>
|
||||
<path d="M2880 3634 c0 -8 5 -12 10 -9 6 4 8 11 5 16 -9 14 -15 11 -15 -7z"/>
|
||||
<path d="M4640 3639 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M2970 3620 c0 -5 9 -14 20 -20 22 -12 27 -1 8 18 -14 14 -28 16 -28
|
||||
2z"/>
|
||||
<path d="M500 3601 c0 -25 6 -27 13 -6 4 8 2 17 -3 20 -6 4 -10 -3 -10 -14z"/>
|
||||
<path d="M1815 3610 c3 -5 11 -10 16 -10 6 0 7 5 4 10 -3 6 -11 10 -16 10 -6
|
||||
0 -7 -4 -4 -10z"/>
|
||||
<path d="M3452 3595 c0 -16 2 -22 5 -12 2 9 2 23 0 30 -3 6 -5 -1 -5 -18z"/>
|
||||
<path d="M761 3594 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M2278 3603 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
|
||||
<path d="M3030 3576 c0 -9 5 -16 10 -16 6 0 10 4 10 9 0 6 -4 13 -10 16 -5 3
|
||||
-10 -1 -10 -9z"/>
|
||||
<path d="M3416 3565 c-22 -34 -20 -43 4 -15 18 21 26 40 16 40 -2 0 -11 -11
|
||||
-20 -25z"/>
|
||||
<path d="M4418 3573 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
|
||||
<path d="M3534 3529 c3 -17 6 -40 6 -51 0 -10 4 -17 9 -13 6 3 6 18 1 36 -5
|
||||
16 -6 37 -3 45 3 8 0 14 -7 14 -9 0 -11 -10 -6 -31z"/>
|
||||
<path d="M746 3488 c-9 -84 -13 -299 -6 -338 3 -19 8 60 11 175 3 116 4 212 3
|
||||
213 -1 2 -5 -20 -8 -50z"/>
|
||||
<path d="M5611 3504 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M3520 3455 c-1 -12 -4 -15 -7 -7 -4 10 -8 9 -19 -5 -16 -21 -18 -62
|
||||
-4 -83 8 -13 10 -12 10 3 0 19 19 58 34 68 4 4 3 15 -3 25 -10 18 -10 18 -11
|
||||
-1z"/>
|
||||
<path d="M4995 3450 c-3 -5 1 -10 10 -10 9 0 13 5 10 10 -3 6 -8 10 -10 10 -2
|
||||
0 -7 -4 -10 -10z"/>
|
||||
<path d="M2940 3429 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M3447 3397 c-3 -9 -1 -19 4 -23 7 -4 8 -21 4 -41 -4 -24 -3 -33 4
|
||||
-28 12 7 13 60 2 89 -7 17 -8 18 -14 3z"/>
|
||||
<path d="M1358 3393 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
|
||||
<path d="M5323 3393 c9 -2 23 -2 30 0 6 3 -1 5 -18 5 -16 0 -22 -2 -12 -5z"/>
|
||||
<path d="M1285 3375 c-40 -14 -40 -14 -5 -8 19 3 42 9 50 14 22 12 1 9 -45 -6z"/>
|
||||
<path d="M5403 3383 c9 -2 15 -9 12 -14 -4 -5 -2 -9 3 -9 6 0 12 7 16 15 4 11
|
||||
-2 15 -22 14 -17 -1 -20 -3 -9 -6z"/>
|
||||
<path d="M2957 3353 c-4 -3 -8 -22 -8 -42 l-2 -36 -6 35 c-4 23 -9 31 -14 23
|
||||
-6 -10 18 -83 28 -83 1 0 3 21 4 47 2 72 11 64 11 -11 0 -42 4 -65 10 -61 6 4
|
||||
10 -6 10 -24 0 -16 5 -33 10 -36 14 -9 5 62 -11 81 -6 8 -9 27 -6 43 10 46 -6
|
||||
85 -26 64z"/>
|
||||
<path d="M3421 3324 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M1108 3323 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
|
||||
<path d="M3382 3270 c0 -27 3 -50 9 -50 5 0 9 12 9 28 0 15 3 37 6 50 5 15 2
|
||||
22 -8 22 -11 0 -15 -14 -16 -50z"/>
|
||||
<path d="M3750 3301 c0 -6 4 -13 10 -16 6 -3 7 1 4 9 -7 18 -14 21 -14 7z"/>
|
||||
<path d="M3451 3224 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M5150 3230 c20 -13 33 -13 25 0 -3 6 -14 10 -23 10 -15 0 -15 -2 -2
|
||||
-10z"/>
|
||||
<path d="M1277 3219 c7 -7 15 -10 18 -7 3 3 -2 9 -12 12 -14 6 -15 5 -6 -5z"/>
|
||||
<path d="M2250 3199 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M5090 3189 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M3020 3179 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M5000 3180 l-45 -7 45 -1 c25 -1 52 3 60 8 18 11 13 11 -60 0z"/>
|
||||
<path d="M2377 3173 c-3 -5 1 -14 9 -20 14 -14 30 0 19 17 -7 12 -22 13 -28 3z"/>
|
||||
<path d="M3311 3154 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M3027 3136 c3 -14 16 -34 29 -47 l23 -22 -3 29 c-6 45 -17 64 -36 64
|
||||
-13 0 -16 -6 -13 -24z"/>
|
||||
<path d="M4841 3156 c2 -2 15 -9 29 -15 24 -11 24 -11 6 3 -16 13 -49 24 -35
|
||||
12z"/>
|
||||
<path d="M2687 3143 c-4 -3 -7 -11 -7 -17 0 -6 5 -5 12 2 6 6 9 14 7 17 -3 3
|
||||
-9 2 -12 -2z"/>
|
||||
<path d="M747 3025 c3 -49 9 -94 13 -98 8 -9 3 55 -10 138 -6 36 -7 25 -3 -40z"/>
|
||||
<path d="M4180 3102 c0 -5 7 -15 15 -22 8 -7 15 -9 15 -6 0 4 -7 14 -15 22 -8
|
||||
9 -15 11 -15 6z"/>
|
||||
<path d="M4718 3103 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
|
||||
<path d="M3269 3080 c-2 -14 -10 -24 -17 -22 -6 1 -12 -2 -12 -8 0 -15 30 -12
|
||||
36 4 3 8 4 23 2 33 -4 14 -6 12 -9 -7z"/>
|
||||
<path d="M3577 3093 c-4 -3 -7 -11 -7 -17 0 -6 5 -5 12 2 6 6 9 14 7 17 -3 3
|
||||
-9 2 -12 -2z"/>
|
||||
<path d="M3097 3070 c3 -11 7 -20 9 -20 2 0 4 9 4 20 0 11 -4 20 -9 20 -5 0
|
||||
-7 -9 -4 -20z"/>
|
||||
<path d="M1568 3073 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
|
||||
<path d="M1628 3073 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
|
||||
<path d="M4257 3020 c12 -19 27 -36 34 -39 7 -2 2 10 -10 27 -31 44 -50 53
|
||||
-24 12z"/>
|
||||
<path d="M4553 3035 c0 -8 5 -11 10 -8 6 3 26 6 46 5 28 0 32 1 16 8 -33 14
|
||||
-72 12 -72 -5z"/>
|
||||
<path d="M3130 3016 c0 -8 5 -18 10 -21 6 -3 10 1 10 9 0 8 -4 18 -10 21 -5 3
|
||||
-10 -1 -10 -9z"/>
|
||||
<path d="M4160 3010 c0 -9 39 -25 46 -18 2 3 -7 10 -21 16 -14 6 -25 7 -25 2z"/>
|
||||
<path d="M4003 2993 c-18 -7 -16 -23 2 -23 8 0 15 -4 15 -10 0 -5 7 -10 15
|
||||
-10 18 0 20 16 3 23 -7 3 -4 6 7 6 17 1 17 3 5 11 -16 10 -28 11 -47 3z"/>
|
||||
<path d="M2890 2975 c0 -8 4 -15 10 -15 5 0 7 7 4 15 -4 8 -8 15 -10 15 -2 0
|
||||
-4 -7 -4 -15z"/>
|
||||
<path d="M4227 2979 c7 -7 15 -10 18 -7 3 3 -2 9 -12 12 -14 6 -15 5 -6 -5z"/>
|
||||
<path d="M1708 2973 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
|
||||
<path d="M4465 2970 c3 -5 14 -10 23 -10 15 0 15 2 2 10 -20 13 -33 13 -25 0z"/>
|
||||
<path d="M2865 2960 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
|
||||
-7 -4 -4 -10z"/>
|
||||
<path d="M2600 2889 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M5510 2660 c-3 -102 -3 -230 0 -285 l5 -100 5 140 c3 77 3 205 0 285
|
||||
l-6 145 -4 -185z"/>
|
||||
<path d="M791 2744 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M881 2625 c-8 -48 -9 -156 -4 -230 10 -129 19 -40 12 115 -3 74 -7
|
||||
126 -8 115z"/>
|
||||
<path d="M2710 2489 c0 -16 29 -41 40 -34 6 4 5 13 -3 25 -13 21 -37 27 -37 9z"/>
|
||||
<path d="M1177 2344 c-4 -4 -7 -20 -7 -36 0 -23 4 -29 18 -26 11 3 16 12 14
|
||||
28 -3 28 -15 44 -25 34z"/>
|
||||
<path d="M1150 2270 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
|
||||
-4 -4 -4 -10z"/>
|
||||
<path d="M1290 2229 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
|
||||
-5 -10 -11z"/>
|
||||
<path d="M2665 2170 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
|
||||
-7 -4 -4 -10z"/>
|
||||
<path d="M1050 2057 c0 -11 70 -137 76 -137 10 0 1 19 -36 80 -22 36 -40 61
|
||||
-40 57z"/>
|
||||
<path d="M1141 1894 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M3768 1883 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
|
||||
<path d="M1160 1865 c0 -8 4 -15 10 -15 5 0 7 7 4 15 -4 8 -8 15 -10 15 -2 0
|
||||
-4 -7 -4 -15z"/>
|
||||
<path d="M3690 1860 c6 -11 13 -20 16 -20 2 0 0 9 -6 20 -6 11 -13 20 -16 20
|
||||
-2 0 0 -9 6 -20z"/>
|
||||
<path d="M1190 1822 c6 -13 14 -21 18 -18 3 4 -2 14 -12 24 -18 16 -18 16 -6
|
||||
-6z"/>
|
||||
<path d="M3541 1824 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M3650 1790 c0 -5 10 -10 23 -10 18 0 19 2 7 10 -19 13 -30 13 -30 0z"/>
|
||||
<path d="M3659 1758 c-12 -8 -11 -9 2 -5 9 3 22 0 28 -6 6 -6 13 -8 17 -5 12
|
||||
12 -31 27 -47 16z"/>
|
||||
<path d="M3710 1707 c8 -7 20 -19 27 -26 9 -11 11 -10 9 3 -2 18 -23 36 -41
|
||||
36 -5 -1 -3 -6 5 -13z"/>
|
||||
<path d="M3760 1630 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
|
||||
-4 -4 -4 -10z"/>
|
||||
<path d="M3532 1580 c0 -14 2 -19 5 -12 2 6 2 18 0 25 -3 6 -5 1 -5 -13z"/>
|
||||
<path d="M3791 1574 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M3876 1473 c-12 -12 -6 -31 12 -38 14 -5 15 -4 5 6 -18 18 -16 30 2
|
||||
23 8 -4 15 -4 15 -1 0 8 -28 16 -34 10z"/>
|
||||
<path d="M3861 1374 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M3935 1360 c3 -5 11 -10 16 -10 6 0 7 5 4 10 -3 6 -11 10 -16 10 -6
|
||||
0 -7 -4 -4 -10z"/>
|
||||
<path d="M4110 1300 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
|
||||
-4 -4 -4 -10z"/>
|
||||
<path d="M3700 1236 c0 -2 7 -7 16 -10 8 -3 12 -2 9 4 -6 10 -25 14 -25 6z"/>
|
||||
<path d="M4130 1211 c0 -6 4 -13 10 -16 6 -3 7 1 4 9 -7 18 -14 21 -14 7z"/>
|
||||
<path d="M4133 1160 c14 -63 18 -138 9 -144 -22 -13 -211 91 -237 130 -9 14
|
||||
-19 23 -22 20 -3 -2 -5 -56 -4 -119 2 -119 -3 -151 -23 -140 -6 4 -5 0 2 -9 8
|
||||
-9 20 -14 28 -11 19 7 21 36 8 172 -5 50 -3 62 8 59 7 -3 13 -12 12 -20 -1 -8
|
||||
9 -15 24 -16 13 -1 39 -11 57 -22 18 -11 38 -20 45 -20 6 0 24 -8 38 -19 15
|
||||
-10 39 -21 54 -25 25 -6 27 -4 30 31 4 46 -11 134 -25 148 -6 7 -8 2 -4 -15z"/>
|
||||
<path d="M1561 1144 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M4173 1153 c9 -2 23 -2 30 0 6 3 -1 5 -18 5 -16 0 -22 -2 -12 -5z"/>
|
||||
<path d="M872 1125 c0 -16 2 -22 5 -12 2 9 2 23 0 30 -3 6 -5 -1 -5 -18z"/>
|
||||
<path d="M866 1053 c-3 -21 -6 -82 -6 -135 l0 -98 53 2 52 1 -45 6 -45 6 4
|
||||
128 c3 128 -1 159 -13 90z"/>
|
||||
<path d="M3624 1067 c-3 -10 -2 -23 4 -29 6 -6 8 -17 5 -25 -3 -7 -2 -13 3
|
||||
-11 15 5 74 -24 68 -33 -3 -5 3 -9 13 -9 10 0 35 -11 55 -25 20 -14 45 -25 55
|
||||
-25 10 0 1 9 -22 21 -61 32 -144 99 -160 128 -12 23 -14 24 -21 8z"/>
|
||||
<path d="M3655 1070 c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0
|
||||
-8 -4 -11 -10z"/>
|
||||
<path d="M3400 951 c0 -42 -4 -39 125 -81 21 -7 46 -19 53 -27 19 -19 45 -13
|
||||
48 12 11 68 15 139 8 132 -4 -4 -9 -20 -11 -35 -4 -41 -25 -102 -35 -102 -4 0
|
||||
-8 5 -8 10 0 6 -5 10 -11 10 -6 0 -24 9 -39 20 -20 14 -29 17 -32 8 -3 -8 -19
|
||||
-1 -48 20 -27 20 -37 32 -27 32 10 0 25 -9 34 -20 10 -11 22 -20 27 -20 6 0
|
||||
-8 18 -29 40 -21 22 -43 40 -47 40 -4 0 -8 -17 -8 -39z"/>
|
||||
<path d="M3355 939 c-4 -6 -5 -13 -2 -16 7 -7 27 6 27 18 0 12 -17 12 -25 -2z"/>
|
||||
<path d="M5500 883 l0 -62 -57 -6 c-98 -10 -101 -13 -15 -12 l84 2 4 53 c2 29
|
||||
0 61 -6 70 -7 13 -9 0 -10 -45z"/>
|
||||
<path d="M3374 808 c-3 -4 15 -8 40 -8 25 0 47 4 50 8 2 4 -16 8 -40 8 -25 0
|
||||
-48 -4 -50 -8z"/>
|
||||
<path d="M3488 813 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 61 KiB |
@ -1,19 +0,0 @@
|
||||
{
|
||||
"name": "Nexus Cognitron",
|
||||
"short_name": "Nexus Cognitron",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
4
nexus/cognitron/web/tsconfig.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
// https://v3.nuxtjs.org/concepts/typescript
|
||||
"extends": "./.nuxt/tsconfig.json"
|
||||
}
|
@ -26,25 +26,24 @@ py3_image(
|
||||
requirement("aiodns"),
|
||||
requirement("aiohttp"),
|
||||
requirement("aiohttp_socks"),
|
||||
requirement("aioipfs"),
|
||||
requirement("cchardet"),
|
||||
requirement("orjson"),
|
||||
requirement("prometheus-client"),
|
||||
requirement("psycopg2-binary"),
|
||||
requirement("python-socks"),
|
||||
requirement("tenacity"),
|
||||
requirement("uvloop"),
|
||||
"//idm/api/proto:idm_proto_py",
|
||||
"//idm/api/proto:proto_py",
|
||||
requirement("aiogrobid"),
|
||||
"//library/aiogrpctools",
|
||||
"//library/aioipfs",
|
||||
requirement("aiokit"),
|
||||
"//library/aiopostgres",
|
||||
"//library/configurator",
|
||||
"//library/telegram",
|
||||
"//nexus/hub/proto:hub_grpc_py",
|
||||
"//nexus/hub/proto:hub_proto_py",
|
||||
"//nexus/hub/proto:grpc_py",
|
||||
"//nexus/hub/proto:proto_py",
|
||||
"//nexus/meta_api/aioclient",
|
||||
"//nexus/models/proto:models_proto_py",
|
||||
"//nexus/models/proto:proto_py",
|
||||
"//nexus/pylon",
|
||||
"//nexus/views/telegram",
|
||||
],
|
||||
@ -54,7 +53,7 @@ container_push(
|
||||
name = "push-latest",
|
||||
format = "Docker",
|
||||
image = ":image",
|
||||
registry = "registry.example.com",
|
||||
registry = "registry.infra.svc.cluster.local",
|
||||
repository = "nexus-hub",
|
||||
tag = "latest",
|
||||
)
|
||||
@ -63,7 +62,7 @@ container_push(
|
||||
name = "push-testing",
|
||||
format = "Docker",
|
||||
image = ":image",
|
||||
registry = "registry.example.com",
|
||||
registry = "registry.infra.svc.cluster.local",
|
||||
repository = "nexus-hub",
|
||||
tag = "testing",
|
||||
)
|
||||
|
@ -6,11 +6,11 @@ py_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
requirement("grpcio"),
|
||||
"//idm/api/proto:idm_proto_py",
|
||||
"//idm/api/proto:proto_py",
|
||||
requirement("aiogrpcclient"),
|
||||
requirement("aiokit"),
|
||||
"//nexus/hub/proto:hub_grpc_py",
|
||||
"//nexus/hub/proto:hub_proto_py",
|
||||
"//nexus/models/proto:models_proto_py",
|
||||
"//nexus/hub/proto:grpc_py",
|
||||
"//nexus/hub/proto:proto_py",
|
||||
"//nexus/models/proto:proto_py",
|
||||
],
|
||||
)
|
||||
|
@ -26,13 +26,15 @@ class HubGrpcClient(BaseGrpcClient):
|
||||
self,
|
||||
typed_document_pb: TypedDocumentPb,
|
||||
chat: ChatPb,
|
||||
request_id: Optional[str],
|
||||
session_id: Optional[str],
|
||||
bot_name: str,
|
||||
request_id: Optional[str] = None,
|
||||
session_id: Optional[str] = None,
|
||||
) -> StartDeliveryResponsePb:
|
||||
return await self.stubs['delivery'].start_delivery(
|
||||
StartDeliveryRequestPb(
|
||||
typed_document=typed_document_pb,
|
||||
chat=chat,
|
||||
bot_name=bot_name,
|
||||
),
|
||||
metadata=(('request-id', request_id), ('session-id', session_id))
|
||||
)
|
||||
@ -42,6 +44,7 @@ class HubGrpcClient(BaseGrpcClient):
|
||||
telegram_document: bytes,
|
||||
telegram_file_id: str,
|
||||
chat: ChatPb,
|
||||
bot_name: str,
|
||||
request_id: Optional[str] = None,
|
||||
session_id: Optional[str] = None,
|
||||
) -> SubmitResponsePb:
|
||||
@ -50,6 +53,7 @@ class HubGrpcClient(BaseGrpcClient):
|
||||
telegram_document=telegram_document,
|
||||
telegram_file_id=telegram_file_id,
|
||||
chat=chat,
|
||||
bot_name=bot_name,
|
||||
),
|
||||
metadata=(('request-id', request_id), ('session-id', session_id))
|
||||
)
|
||||
|
@ -23,7 +23,7 @@ grpc:
|
||||
# Listen address
|
||||
address: 0.0.0.0
|
||||
# Listen port
|
||||
port: 9090
|
||||
port: 82
|
||||
ipfs:
|
||||
address: localhost
|
||||
port: 4001
|
||||
@ -36,12 +36,13 @@ pylon:
|
||||
# Proxy used in `pylon` retriever to get metadata
|
||||
resolve_proxy: socks5://127.0.0.1:9050
|
||||
telegram:
|
||||
bots:
|
||||
_policy: merge
|
||||
libgen_scihub_1_bot:
|
||||
# Telegram App Hash from https://my.telegram.org/
|
||||
app_hash:
|
||||
# Telegram App ID from https://my.telegram.org/
|
||||
app_id: 00000
|
||||
# External bot name shown in messages to users
|
||||
bot_external_name: libgen_scihub_bot
|
||||
# Internal bot name used in logging
|
||||
bot_name: nexus-hub
|
||||
bot_token:
|
||||
|
@ -19,37 +19,37 @@ class GrpcServer(AioGrpcServer):
|
||||
self.pool_holder = None
|
||||
if config['database']['enabled']:
|
||||
self.pool_holder = AioPostgresPoolHolder(
|
||||
dsn=f'dbname={config["database"]["database"]} '
|
||||
conninfo=f'dbname={config["database"]["database"]} '
|
||||
f'user={config["database"]["username"]} '
|
||||
f'password={config["database"]["password"]} '
|
||||
f'host={config["database"]["host"]}',
|
||||
timeout=30,
|
||||
pool_recycle=60,
|
||||
maxsize=4,
|
||||
)
|
||||
self.waits.append(self.pool_holder)
|
||||
|
||||
self.telegram_client = BaseTelegramClient(
|
||||
app_id=config['telegram']['app_id'],
|
||||
app_hash=config['telegram']['app_hash'],
|
||||
bot_token=config['telegram']['bot_token'],
|
||||
database=config['telegram'].get('database'),
|
||||
mtproxy=config['telegram'].get('mtproxy'),
|
||||
self.telegram_clients = {}
|
||||
for telegram_bot in config['telegram']['bots']:
|
||||
telegram_bot_config = config['telegram']['bots'][telegram_bot]
|
||||
telegram_client = BaseTelegramClient(
|
||||
app_id=telegram_bot_config['app_id'],
|
||||
app_hash=telegram_bot_config['app_hash'],
|
||||
bot_token=telegram_bot_config['bot_token'],
|
||||
database=telegram_bot_config.get('database'),
|
||||
mtproxy=telegram_bot_config.get('mtproxy'),
|
||||
)
|
||||
self.starts.append(self.telegram_client)
|
||||
self.telegram_clients[telegram_bot] = telegram_client
|
||||
self.starts.extend(self.telegram_clients.values())
|
||||
|
||||
self.delivery_service = DeliveryService(
|
||||
server=self.server,
|
||||
service_name=config['application']['service_name'],
|
||||
bot_external_name=config['telegram']['bot_external_name'],
|
||||
ipfs_config=config['ipfs'],
|
||||
is_sharience_enabled=config['application']['is_sharience_enabled'],
|
||||
maintenance_picture_url=config['application'].get('maintenance_picture_url', ''),
|
||||
pool_holder=self.pool_holder,
|
||||
pylon_config=config['pylon'],
|
||||
should_store_hashes=config['application']['should_store_hashes'],
|
||||
should_use_telegram_file_id=config['telegram']['should_use_telegram_file_id'],
|
||||
telegram_client=self.telegram_client,
|
||||
telegram_clients=self.telegram_clients,
|
||||
telegram_bot_configs=config['telegram']['bots'],
|
||||
)
|
||||
self.starts.append(self.delivery_service)
|
||||
|
||||
@ -57,11 +57,10 @@ class GrpcServer(AioGrpcServer):
|
||||
self.submitter_service = SubmitterService(
|
||||
server=self.server,
|
||||
service_name=config['application']['service_name'],
|
||||
bot_external_name=config['telegram']['bot_external_name'],
|
||||
grobid_config=config['grobid'],
|
||||
ipfs_config=config['ipfs'],
|
||||
meta_api_config=config['meta_api'],
|
||||
telegram_client=self.telegram_client,
|
||||
telegram_clients=self.telegram_clients,
|
||||
)
|
||||
self.starts.append(self.submitter_service)
|
||||
|
||||
|
@ -4,24 +4,24 @@ load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
proto_library(
|
||||
name = "hub_proto",
|
||||
name = "proto",
|
||||
srcs = glob([
|
||||
"*.proto",
|
||||
]),
|
||||
deps = [
|
||||
"//idm/api/proto:idm_proto",
|
||||
"//nexus/models/proto:models_proto",
|
||||
"//idm/api/proto",
|
||||
"//nexus/models/proto",
|
||||
"@com_google_protobuf//:wrappers_proto",
|
||||
],
|
||||
)
|
||||
|
||||
py_proto_library(
|
||||
name = "hub_proto_py",
|
||||
deps = [":hub_proto"],
|
||||
name = "proto_py",
|
||||
deps = [":proto"],
|
||||
)
|
||||
|
||||
py_grpc_library(
|
||||
name = "hub_grpc_py",
|
||||
srcs = [":hub_proto"],
|
||||
deps = [":hub_proto_py"],
|
||||
name = "grpc_py",
|
||||
srcs = [":proto"],
|
||||
deps = [":proto_py"],
|
||||
)
|
||||
|
@ -7,6 +7,7 @@ import "idm/api/proto/chat_manager_service.proto";
|
||||
message StartDeliveryRequest {
|
||||
nexus.models.proto.TypedDocument typed_document = 1;
|
||||
idm.api.proto.Chat chat = 2;
|
||||
string bot_name = 3;
|
||||
}
|
||||
|
||||
message StartDeliveryResponse {
|
||||
|
@ -1,184 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: nexus/hub/proto/delivery_service.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
from idm.api.proto import \
|
||||
chat_manager_service_pb2 as \
|
||||
idm_dot_api_dot_proto_dot_chat__manager__service__pb2
|
||||
from nexus.models.proto import \
|
||||
typed_document_pb2 as nexus_dot_models_dot_proto_dot_typed__document__pb2
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name='nexus/hub/proto/delivery_service.proto',
|
||||
package='nexus.hub.proto',
|
||||
syntax='proto3',
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
serialized_pb=b'\n&nexus/hub/proto/delivery_service.proto\x12\x0fnexus.hub.proto\x1a\'nexus/models/proto/typed_document.proto\x1a(idm/api/proto/chat_manager_service.proto\"t\n\x14StartDeliveryRequest\x12\x39\n\x0etyped_document\x18\x01 \x01(\x0b\x32!.nexus.models.proto.TypedDocument\x12!\n\x04\x63hat\x18\x02 \x01(\x0b\x32\x13.idm.api.proto.Chat\"\x99\x01\n\x15StartDeliveryResponse\x12=\n\x06status\x18\x01 \x01(\x0e\x32-.nexus.hub.proto.StartDeliveryResponse.Status\"A\n\x06Status\x12\x06\n\x02OK\x10\x00\x12\x16\n\x12TOO_MANY_DOWNLOADS\x10\x01\x12\x17\n\x13\x41LREADY_DOWNLOADING\x10\x02\x32m\n\x08\x44\x65livery\x12\x61\n\x0estart_delivery\x12%.nexus.hub.proto.StartDeliveryRequest\x1a&.nexus.hub.proto.StartDeliveryResponse\"\x00\x62\x06proto3'
|
||||
,
|
||||
dependencies=[nexus_dot_models_dot_proto_dot_typed__document__pb2.DESCRIPTOR,idm_dot_api_dot_proto_dot_chat__manager__service__pb2.DESCRIPTOR,])
|
||||
|
||||
|
||||
|
||||
_STARTDELIVERYRESPONSE_STATUS = _descriptor.EnumDescriptor(
|
||||
name='Status',
|
||||
full_name='nexus.hub.proto.StartDeliveryResponse.Status',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
values=[
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='OK', index=0, number=0,
|
||||
serialized_options=None,
|
||||
type=None,
|
||||
create_key=_descriptor._internal_create_key),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='TOO_MANY_DOWNLOADS', index=1, number=1,
|
||||
serialized_options=None,
|
||||
type=None,
|
||||
create_key=_descriptor._internal_create_key),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='ALREADY_DOWNLOADING', index=2, number=2,
|
||||
serialized_options=None,
|
||||
type=None,
|
||||
create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
containing_type=None,
|
||||
serialized_options=None,
|
||||
serialized_start=349,
|
||||
serialized_end=414,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_STARTDELIVERYRESPONSE_STATUS)
|
||||
|
||||
|
||||
_STARTDELIVERYREQUEST = _descriptor.Descriptor(
|
||||
name='StartDeliveryRequest',
|
||||
full_name='nexus.hub.proto.StartDeliveryRequest',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='typed_document', full_name='nexus.hub.proto.StartDeliveryRequest.typed_document', index=0,
|
||||
number=1, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='chat', full_name='nexus.hub.proto.StartDeliveryRequest.chat', index=1,
|
||||
number=2, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=142,
|
||||
serialized_end=258,
|
||||
)
|
||||
|
||||
|
||||
_STARTDELIVERYRESPONSE = _descriptor.Descriptor(
|
||||
name='StartDeliveryResponse',
|
||||
full_name='nexus.hub.proto.StartDeliveryResponse',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='status', full_name='nexus.hub.proto.StartDeliveryResponse.status', index=0,
|
||||
number=1, type=14, cpp_type=8, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
_STARTDELIVERYRESPONSE_STATUS,
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=261,
|
||||
serialized_end=414,
|
||||
)
|
||||
|
||||
_STARTDELIVERYREQUEST.fields_by_name['typed_document'].message_type = nexus_dot_models_dot_proto_dot_typed__document__pb2._TYPEDDOCUMENT
|
||||
_STARTDELIVERYREQUEST.fields_by_name['chat'].message_type = idm_dot_api_dot_proto_dot_chat__manager__service__pb2._CHAT
|
||||
_STARTDELIVERYRESPONSE.fields_by_name['status'].enum_type = _STARTDELIVERYRESPONSE_STATUS
|
||||
_STARTDELIVERYRESPONSE_STATUS.containing_type = _STARTDELIVERYRESPONSE
|
||||
DESCRIPTOR.message_types_by_name['StartDeliveryRequest'] = _STARTDELIVERYREQUEST
|
||||
DESCRIPTOR.message_types_by_name['StartDeliveryResponse'] = _STARTDELIVERYRESPONSE
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
StartDeliveryRequest = _reflection.GeneratedProtocolMessageType('StartDeliveryRequest', (_message.Message,), {
|
||||
'DESCRIPTOR' : _STARTDELIVERYREQUEST,
|
||||
'__module__' : 'nexus.hub.proto.delivery_service_pb2'
|
||||
# @@protoc_insertion_point(class_scope:nexus.hub.proto.StartDeliveryRequest)
|
||||
})
|
||||
_sym_db.RegisterMessage(StartDeliveryRequest)
|
||||
|
||||
StartDeliveryResponse = _reflection.GeneratedProtocolMessageType('StartDeliveryResponse', (_message.Message,), {
|
||||
'DESCRIPTOR' : _STARTDELIVERYRESPONSE,
|
||||
'__module__' : 'nexus.hub.proto.delivery_service_pb2'
|
||||
# @@protoc_insertion_point(class_scope:nexus.hub.proto.StartDeliveryResponse)
|
||||
})
|
||||
_sym_db.RegisterMessage(StartDeliveryResponse)
|
||||
|
||||
|
||||
|
||||
_DELIVERY = _descriptor.ServiceDescriptor(
|
||||
name='Delivery',
|
||||
full_name='nexus.hub.proto.Delivery',
|
||||
file=DESCRIPTOR,
|
||||
index=0,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
serialized_start=416,
|
||||
serialized_end=525,
|
||||
methods=[
|
||||
_descriptor.MethodDescriptor(
|
||||
name='start_delivery',
|
||||
full_name='nexus.hub.proto.Delivery.start_delivery',
|
||||
index=0,
|
||||
containing_service=None,
|
||||
input_type=_STARTDELIVERYREQUEST,
|
||||
output_type=_STARTDELIVERYRESPONSE,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
])
|
||||
_sym_db.RegisterServiceDescriptor(_DELIVERY)
|
||||
|
||||
DESCRIPTOR.services_by_name['Delivery'] = _DELIVERY
|
||||
|
||||
# @@protoc_insertion_point(module_scope)
|
@ -1,66 +0,0 @@
|
||||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
from nexus.hub.proto import \
|
||||
delivery_service_pb2 as nexus_dot_hub_dot_proto_dot_delivery__service__pb2
|
||||
|
||||
|
||||
class DeliveryStub(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.start_delivery = channel.unary_unary(
|
||||
'/nexus.hub.proto.Delivery/start_delivery',
|
||||
request_serializer=nexus_dot_hub_dot_proto_dot_delivery__service__pb2.StartDeliveryRequest.SerializeToString,
|
||||
response_deserializer=nexus_dot_hub_dot_proto_dot_delivery__service__pb2.StartDeliveryResponse.FromString,
|
||||
)
|
||||
|
||||
|
||||
class DeliveryServicer(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
def start_delivery(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_DeliveryServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'start_delivery': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.start_delivery,
|
||||
request_deserializer=nexus_dot_hub_dot_proto_dot_delivery__service__pb2.StartDeliveryRequest.FromString,
|
||||
response_serializer=nexus_dot_hub_dot_proto_dot_delivery__service__pb2.StartDeliveryResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'nexus.hub.proto.Delivery', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class Delivery(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
@staticmethod
|
||||
def start_delivery(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/nexus.hub.proto.Delivery/start_delivery',
|
||||
nexus_dot_hub_dot_proto_dot_delivery__service__pb2.StartDeliveryRequest.SerializeToString,
|
||||
nexus_dot_hub_dot_proto_dot_delivery__service__pb2.StartDeliveryResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
@ -7,6 +7,7 @@ message SubmitRequest {
|
||||
bytes telegram_document = 1;
|
||||
string telegram_file_id = 2;
|
||||
idm.api.proto.Chat chat = 3;
|
||||
string bot_name = 4;
|
||||
}
|
||||
message SubmitResponse { }
|
||||
|
||||
|
@ -1,148 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: nexus/hub/proto/submitter_service.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
from idm.api.proto import \
|
||||
chat_manager_service_pb2 as \
|
||||
idm_dot_api_dot_proto_dot_chat__manager__service__pb2
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name='nexus/hub/proto/submitter_service.proto',
|
||||
package='nexus.hub.proto',
|
||||
syntax='proto3',
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
serialized_pb=b'\n\'nexus/hub/proto/submitter_service.proto\x12\x0fnexus.hub.proto\x1a(idm/api/proto/chat_manager_service.proto\"g\n\rSubmitRequest\x12\x19\n\x11telegram_document\x18\x01 \x01(\x0c\x12\x18\n\x10telegram_file_id\x18\x02 \x01(\t\x12!\n\x04\x63hat\x18\x03 \x01(\x0b\x32\x13.idm.api.proto.Chat\"\x10\n\x0eSubmitResponse2X\n\tSubmitter\x12K\n\x06submit\x12\x1e.nexus.hub.proto.SubmitRequest\x1a\x1f.nexus.hub.proto.SubmitResponse\"\x00\x62\x06proto3'
|
||||
,
|
||||
dependencies=[idm_dot_api_dot_proto_dot_chat__manager__service__pb2.DESCRIPTOR,])
|
||||
|
||||
|
||||
|
||||
|
||||
_SUBMITREQUEST = _descriptor.Descriptor(
|
||||
name='SubmitRequest',
|
||||
full_name='nexus.hub.proto.SubmitRequest',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='telegram_document', full_name='nexus.hub.proto.SubmitRequest.telegram_document', index=0,
|
||||
number=1, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=b"",
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='telegram_file_id', full_name='nexus.hub.proto.SubmitRequest.telegram_file_id', index=1,
|
||||
number=2, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='chat', full_name='nexus.hub.proto.SubmitRequest.chat', index=2,
|
||||
number=3, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=102,
|
||||
serialized_end=205,
|
||||
)
|
||||
|
||||
|
||||
_SUBMITRESPONSE = _descriptor.Descriptor(
|
||||
name='SubmitResponse',
|
||||
full_name='nexus.hub.proto.SubmitResponse',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=207,
|
||||
serialized_end=223,
|
||||
)
|
||||
|
||||
_SUBMITREQUEST.fields_by_name['chat'].message_type = idm_dot_api_dot_proto_dot_chat__manager__service__pb2._CHAT
|
||||
DESCRIPTOR.message_types_by_name['SubmitRequest'] = _SUBMITREQUEST
|
||||
DESCRIPTOR.message_types_by_name['SubmitResponse'] = _SUBMITRESPONSE
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
SubmitRequest = _reflection.GeneratedProtocolMessageType('SubmitRequest', (_message.Message,), {
|
||||
'DESCRIPTOR' : _SUBMITREQUEST,
|
||||
'__module__' : 'nexus.hub.proto.submitter_service_pb2'
|
||||
# @@protoc_insertion_point(class_scope:nexus.hub.proto.SubmitRequest)
|
||||
})
|
||||
_sym_db.RegisterMessage(SubmitRequest)
|
||||
|
||||
SubmitResponse = _reflection.GeneratedProtocolMessageType('SubmitResponse', (_message.Message,), {
|
||||
'DESCRIPTOR' : _SUBMITRESPONSE,
|
||||
'__module__' : 'nexus.hub.proto.submitter_service_pb2'
|
||||
# @@protoc_insertion_point(class_scope:nexus.hub.proto.SubmitResponse)
|
||||
})
|
||||
_sym_db.RegisterMessage(SubmitResponse)
|
||||
|
||||
|
||||
|
||||
_SUBMITTER = _descriptor.ServiceDescriptor(
|
||||
name='Submitter',
|
||||
full_name='nexus.hub.proto.Submitter',
|
||||
file=DESCRIPTOR,
|
||||
index=0,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
serialized_start=225,
|
||||
serialized_end=313,
|
||||
methods=[
|
||||
_descriptor.MethodDescriptor(
|
||||
name='submit',
|
||||
full_name='nexus.hub.proto.Submitter.submit',
|
||||
index=0,
|
||||
containing_service=None,
|
||||
input_type=_SUBMITREQUEST,
|
||||
output_type=_SUBMITRESPONSE,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
])
|
||||
_sym_db.RegisterServiceDescriptor(_SUBMITTER)
|
||||
|
||||
DESCRIPTOR.services_by_name['Submitter'] = _SUBMITTER
|
||||
|
||||
# @@protoc_insertion_point(module_scope)
|
@ -1,67 +0,0 @@
|
||||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
from nexus.hub.proto import \
|
||||
submitter_service_pb2 as \
|
||||
nexus_dot_hub_dot_proto_dot_submitter__service__pb2
|
||||
|
||||
|
||||
class SubmitterStub(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.submit = channel.unary_unary(
|
||||
'/nexus.hub.proto.Submitter/submit',
|
||||
request_serializer=nexus_dot_hub_dot_proto_dot_submitter__service__pb2.SubmitRequest.SerializeToString,
|
||||
response_deserializer=nexus_dot_hub_dot_proto_dot_submitter__service__pb2.SubmitResponse.FromString,
|
||||
)
|
||||
|
||||
|
||||
class SubmitterServicer(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
def submit(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_SubmitterServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'submit': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.submit,
|
||||
request_deserializer=nexus_dot_hub_dot_proto_dot_submitter__service__pb2.SubmitRequest.FromString,
|
||||
response_serializer=nexus_dot_hub_dot_proto_dot_submitter__service__pb2.SubmitResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'nexus.hub.proto.Submitter', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class Submitter(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
@staticmethod
|
||||
def submit(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/nexus.hub.proto.Submitter/submit',
|
||||
nexus_dot_hub_dot_proto_dot_submitter__service__pb2.SubmitRequest.SerializeToString,
|
||||
nexus_dot_hub_dot_proto_dot_submitter__service__pb2.SubmitResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|