рдХрд┐рд╕ рд▓рд┐рдП
рд╡рд┐рдЬреНрдЮрд╛рдкрди рдЕрднрд┐рдпрд╛рдиреЛрдВ рдХреА рдЬрдЯрд┐рд▓ рд╕рдВрд░рдЪрдирд╛ рдФрд░ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдХреЙрд▓ рдХреЗ рд╕рд╛рде, рдЗрдирдХрдорд┐рдВрдЧ рдХреЙрд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рднрдВрдбрд╛рд░рдг, рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдФрд░ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рдЙрдкрдХрд░рдг рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред рдЕрдХреНрд╕рд░ рдЖрдкрдХреЛ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдбреЗрдЯрд╛ рддрдХ рддреНрд╡рд░рд┐рдд рдкрд╣реБрдВрдЪ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдХрднреА-рдХрднреА рдЖрдкрдХреЛ рдЬрдЯрд┐рд▓ рдбреЗрдЯрд╛ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЪреИрдирд▓ рдпрд╛ рдЕрднрд┐рдпрд╛рди рдХреЗ рд▓рд┐рдП рд╕рд╣рд╕рдВрдмрдВрдзреА рдХреЙрд▓ред
рдХрд╛рдо рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рдХрд▓реНрдкреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ, рдЬреЛ рдЕрддрд┐рд░рд┐рдХреНрдд рд▓рд╛рдн рднреА рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, CoMagic рд╕реЗ Google BigQuery рдХреЛ рдХреЙрд▓ рдЖрдпрд╛рдд рдХрд░ рд░рд╣рд╛ рд╣реИред рдмрд╣реБрдд рдЕрдзрд┐рдХ BigQuery рдХреЗ рд▓рд╛рднреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдЪрд▓рд┐рдП рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред
рдПрдХ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдЖрдпрд╛рдд рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:
- Google рдЦрд╛рддрд╛ (рдпрджрд┐ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рдирд╣реАрдВ рд╣реИ) рдирд┐рд░реНрдорд┐рдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╕рд╛рде
- рдЕрдЬрдЧрд░ рдЬреНрдЮрд╛рди
- рдкреЗрд╢ рд╣реИ рдЧреВрдЧрд▓ рдХреНрд▓рд╛рдЙрдб рдбреЙрдХреНрдпреВрдореЗрдВрдЯреЗрд╢рди
рдХреИрд╕реЗ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП
рдпрд╣рд╛рдБ рд╡рд░реНрдгрд┐рдд
рд╣реИ ред рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ BigQuery рдореЗрдВ рдПрдХ рдбреЗрдЯрд╛рд╕реЗрдЯ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдмреАрдХреНрдпреВ рдкреНрд░рд▓реЗрдЦрди рдФрд░
рдбреЗрдЯрд╛рд╕реЗрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢ ред
CoMagic рд╕реЗ рдбреЗрдЯрд╛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛
CoMagic
рдкреНрд░рд▓реЗрдЦрди рдХреА рдУрд░ рдореБрдбрд╝рддреЗ рд╣реБрдПред рдХреЙрд▓ рдпрд╛ рдХреЙрд▓ рдХреА рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд░рд┐рдкреЛрд░реНрдЯ рдЕрдиреБрднрд╛рдЧ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рд╣рдо CoMagic рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рд╡рд░реНрдЧ рдмрдирд╛рддреЗ рд╣реИрдВред GitHub рдХреЗ рд▓рд┐рдВрдХ рдореЗрдВ рдЕрдВрдд рдореЗрдВ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
import json import requests import random import pandas as pd class ComagicClient: """ CoMagic""" def __init__(self, login, password): """ CoMagic""" self.login = login self.password = password self.base_url = 'https://dataapi.comagic.ru/v2.0' self.payload_ = {"jsonrpc":"2.0", "id":1, "method":None, "params": None} self.token = self.get_token(self.login, self.password) def base_request(self, method, params): """ CoMagic. API . JSON-like . : https://www.comagic.ru/support/api/data-api/""" id_ = random.randrange(10**7)
рдЕрдм рдЖрдкрдХреЛ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдбреЗрдЯрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдбреЗрдЯрд╛ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдФрд░ рджреГрд╢реНрдпрдорд╛рди рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдЗрд╕реЗ BigQuery рдореЗрдВ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред
рдПрдХ рд╕рд╣рд╛рдпрдХ рд╡рд░реНрдЧ рдмрдирд╛рдПрдВ рдФрд░ CoMagic рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВред
class ComagicHandler(ComagicClient): """ , CoMagic""" time_partition_field = 'PARTITION_DATE' def __init__(self, login, password, first_call_date): self.day_before_first_call = pd.to_datetime(first_call_date) - pd.Timedelta(days=1) super().__init__(login, password) def get_calls_report(self, date_from, date_till): """ . . Pandas DataFrame. . Connector . . . Pnadas.DataFrame""" method = "get.calls_report" fields = ['id', 'visitor_id', 'person_id', 'start_time', 'finish_reason', 'is_lost', 'tags', 'campaign_name','communication_number', 'contact_phone_number', 'talk_duration', 'clean_talk_duration', 'virtual_phone_number', 'ua_client_id', 'ym_client_id', 'entrance_page', 'gclid', 'yclid', 'visitor_type', 'visits_count', 'visitor_first_campaign_name', 'visitor_device', 'site_domain_name','utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'eq_utm_source', 'eq_utm_medium', 'eq_utm_campaign', 'attributes']
BigQuery рдХреЛ рдбреЗрдЯрд╛ рднреЗрдЬрдирд╛
CoMagic рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдФрд░ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдЗрд╕реЗ BigQuery рдХреЛ рднреЗрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
from google.cloud import bigquery from google.cloud.exceptions import NotFound import pandas as pd class BQTableHanler: """ BigQuery""" time_partition_field = 'PARTITION_DATE' def __init__(self, full_table_id, service_account_file_key_path = None): """ `myproject.mydataset.mytable`. , Application Default Credentials, .""" self.full_table_id = full_table_id project_id, dataset_id, table_id = full_table_id.split(".") self.project_id = project_id self.dataset_id = dataset_id self.table_id = table_id if service_account_file_key_path:
рдбреЗрдЯрд╛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддрд░реНрдХ рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг рдХрд░реЗрдВ
рдЪреВрдВрдХрд┐ CoMagic рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдкрд░ рдПрдХ рд╕реАрдорд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЕрдиреБрд░реЛрдзрд┐рдд рдбреЗрдЯрд╛ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рд╣рдо рдЕрдиреБрд░реЛрдз рдЕрд╡рдзрд┐ рдХреЛ рд╕реАрдорд┐рдд рдХрд░реЗрдВрдЧреЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рдмрдбрд╝реА рдЕрд╡рдзрд┐ рдХреЛ рдПрдХ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд▓рдВрдмрд╛рдИ рдХреЗ рдЦрдВрдбреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрдЧрд╛ред
def interval_split(array, interval): """ . , 2, - , - . : get_intervals([1,2,3,4,5,6,7], 3) => [[1,3], [4,6], [7]] get_intervals([1,2,3], 4) => [[1,3]]""" intervals = [] iw, i = 0, 0 l = len(array) for v in array: if i==0 or (i)%interval==0: intervals.append([v]) if (i+1)%interval == 0 or (i+1) == l: intervals[iw].append(v) iw+=1 i+=1 return intervals
рдкрд╣рд▓реА рдмрд╛рд░ рдбреЗрдЯрд╛ рд▓реЛрдб рдХрд░рддреЗ рд╕рдордп рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЬрдм рдЖрдкрдХреЛ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдбреЗрдЯрд╛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЕрд╡рдзрд┐ рдХреЛ рдХрдИ рдЫреЛрдЯреЗ рдЕрд╡рдзрд┐рдпреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╡реИрд╕реЗ, рдХреНрд▓рд╛рдЙрдб рдлрдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдРрд╕рд╛ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЙрдирдХреЗ рдкрд╛рд╕ рд╕рдордп рд╕реАрдорд╛ рд╣реИред рдЦреИрд░, рдпрд╛, рдПрдХ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдк рдХрдИ рдмрд╛рд░ рдлрд╝рдВрдХреНрд╢рди рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВред
рд╣рдо BigQuery рдЯреЗрдмрд▓ рдХреЛ рд▓рд┐рдВрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдиреЗрдХреНрдЯрд░ рдХреНрд▓рд╛рд╕ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рд╣рдо рдбреЗрдЯрд╛ рдФрд░ рдбреЗрдЯрд╛ рдХреЛ рдХреЛрдордЬрд┐рдХ рд╕реЗ рд╕реНрдЯреЛрд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред
from helpfunctions import interval_split import pandas as pd class Connector: """ """ time_partition_field = 'PARTITION_DATE'
рдЕрдЧрд▓рд╛, рд╣рдо рдбреЗрдЯрд╛ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЦреНрдп рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдПрдХ рд╢реЗрдбреНрдпреВрд▓ рдкрд░ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
from connector import Connector from bqhandler import BQTableHanler from comagichandler import ComagicHandler from credfile import * def main(event, context): """ event, context : https://cloud.google.com/functions/docs/writing/background#functions-writing-background-hello-pubsub-python"""
Google рдХреНрд▓рд╛рдЙрдб рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ
рд╣рдо рдПрдХ рдЬрд╝рд┐рдк рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рд╕рднреА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рддреЗ рд╣реИрдВред Credfile.py рдлрд╝рд╛рдЗрд▓ рдореЗрдВ, рд╣рдо рдЯреЛрдХрди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП CoMagic рд▓реЙрдЧрд┐рди рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рджрд░реНрдЬ рдХрд░рддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА BigQuery рдореЗрдВ рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдкреВрд░рд╛ рдирд╛рдо рдФрд░ рд╕реНрдерд╛рдиреАрдп рдорд╢реАрди рд╕реЗ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓реЙрдиреНрдЪ рд╣реЛрдиреЗ рдкрд░ рд╕реЗрд╡рд╛ рдЦрд╛рддрд╛ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдкрдеред
рдХреНрд▓рд╛рдЙрдб рдлрдВрдХреНрд╢рди рдмрдирд╛рдПрдВ
- рдХрдВрд╕реЛрд▓ рдкрд░ рдЬрд╛рдПрдВ
- рдпрджрд┐ рдХреЛрдИ рдлрд╝рдВрдХреНрд╢рди рдЕрднреА рддрдХ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ "рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдПрдБ" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ
- рдЯреНрд░рд┐рдЧрд░ рдлрд╝реАрд▓реНрдб рдореЗрдВ, PUB / SUB рдЪреБрдиреЗрдВ
- PUB / SUB рдХреЗ рд▓рд┐рдП рдПрдХ рдирдИ рдереАрдо рдмрдирд╛рдПрдБред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 'update_calls'
- рд╕реНрд░реЛрдд: рдЬрд╝рд┐рдк рдЕрдкрд▓реЛрдб (рд╕реНрдерд╛рдиреАрдп рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓)
- рдкрд░реНрдпрд╛рд╡рд░рдг: рдкрд╛рдпрдерди 3.7
- рдЬрд╝рд┐рдк рдлрд╝рд╛рдЗрд▓ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ
- рдХреНрд▓рд╛рдЙрдб рд╕реНрдЯреЛрд░реЗрдЬ рдХрд╛ рдПрдХ рдЕрд╕реНрдерд╛рдпреА рд╕реЗрдЧрдореЗрдВрдЯ рдЪреБрдирдирд╛
- рдХреНрд╖реЗрддреНрд░ рдореЗрдВ 'рдлрд╝рдВрдХреНрд╢рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ' рд╣рдо 'рдореБрдЦреНрдп' рд▓рд┐рдЦрддреЗ рд╣реИрдВ
- рдЖрд╡рдВрдЯрд┐рдд рд╕реНрдореГрддрд┐: рд╡реИрдХрд▓реНрдкрд┐рдХ

рд╢реЗрдбреНрдпреВрд▓рд░ рдФрд░ PUB / SUB рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛
рдЕрдВрддрд┐рдо рдЪрд░рдг рдореЗрдВ, рд╣рдордиреЗ `update_calls` рдЯреНрд░рд┐рдЧрд░ рдмрдирд╛рдпрд╛ред рдпрд╣ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд╡рд┐рд╖рдп
рд╡рд┐рд╖рдпреЛрдВ рдХреА
рд╕реВрдЪреА рдореЗрдВ рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ рд╣реИред

рдЕрдм, рдХреНрд▓рд╛рдЙрдб рд╢реЗрдбреНрдпреВрд▓рд░ рдХреЗ рд╕рд╛рде рдЖрдкрдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЬрдм рдЖрдЧ рд▓рдЧреЗрдЧреА рдФрд░ рдЬреАрд╕реАрдПрдл рд╢реБрд░реВ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
- рдХрдВрд╕реЛрд▓ рдкрд░ рдЬрд╛рдПрдВ
- CRON рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдЖрд╡реГрддреНрддрд┐ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ, рд╕реЗрдЯ рдХрд░реЗрдВ рдЬрдм рдЯреНрд░рд┐рдЧрд░ рдореЗрдВ рдЖрдЧ рд▓рдЧрдиреА рдЪрд╛рд╣рд┐рдП рдФрд░ рдлрд╝рдВрдХреНрд╢рди рд╢реБрд░реВ рд╣реЛ рдЬрд╛рдПред
- рдЧрдВрддрд╡реНрдп: рдкрдм / рдЙрдк
- рд╡рд┐рд╖рдп: рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рддреЗ рд╕рдордп рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреА рдЧрдИ рд╡рд┐рд╖рдпрд╡рд╕реНрддреБ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдВ: "update_calls"
- рдкреЗрд▓реЛрдбреНрд╕ * (рдкреЗрд▓реЛрдбреНрд╕) - рдпрд╣ рд╡рд╣ рд╕реВрдЪрдирд╛ рд╣реИ рдЬрд┐рд╕реЗ рдкрдм / рд╕рдм рдФрд░ рдореБрдЦреНрдп рд╕рдорд╛рд░реЛрд╣ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛

рдЕрдм рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рджреИрдирд┐рдХ 01:00 рдмрдЬреЗ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдХреЙрд▓ рдбреЗрдЯрд╛ рдХреЛ рдкрд┐рдЫрд▓реЗ рджрд┐рди рдХреЗ рдЕрдВрдд рдореЗрдВ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
GitHub рдХреЛ рд╕реНрдерд╛рдиреАрдп рдХрдВрдкреНрдпреВрдЯрд░ рд╕реЗ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП
рд▓рд┐рдВрдХ рдХрд░реЗрдВGitHub рдЬрд┐рдк рдлрд╛рдЗрд▓ рдХрд╛
рд▓рд┐рдВрдХ