hltv-async-api 0.8.2__tar.gz → 0.8.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hltv_async_api
3
- Version: 0.8.2
3
+ Version: 0.8.3
4
4
  Summary: An unofficial asynchronous HLTV API Wrapper for Python
5
5
  Author: Akim Slys
6
6
  Author-email: akimslys2003@gmail.com
@@ -25,10 +25,9 @@ Description-Content-Type: text/markdown
25
25
 
26
26
  # Future
27
27
 
28
- * **0.8** more event info data (winners, stats, groups, teams), refactor last_matches in player_info. Optimize proxy functions. Coverage.(?) Rotating user agent (exp. till 20.05)
29
- * **0.9.0** stats & images update, more stats scrapers, team logos, player photos, images, more data, team_map stats, map stats, more functions such as get_news_id, get_team_logo, get_player_photo, get_demo_id, get_match_stats...
30
- * **0.10.0** synchronous update, reformatting the library as a synchronous, move async parser as an extension. (JULY-AUGUST 2024)
31
- * **0.11.0 - 1.0.0** Provide to use Hltv-async-api on any system, language, by creating a RESTful service.
28
+ * **0.9.0** (JUNE ?) stats & images update, more stats scrapers, team logos, player photos, images, more data, team_map stats, map stats, more functions such as get_news_id, get_team_logo, get_player_photo, get_demo_id, get_match_stats. Coverage. (?) Rotating user agent
29
+ * **0.10.0** (JULY-AUGUST 2024) synchronous update, reformatting the library as synchronous, move async parser as extension. Rename lib ?.
30
+ * **0.11.0 - 1.0.0** Provide to use Hltv-async-api on any system, language, by creating a RESTful service. (?) Classes. (?)
32
31
 
33
32
 
34
33
  # Features
@@ -2,10 +2,9 @@
2
2
 
3
3
  # Future
4
4
 
5
- * **0.8** more event info data (winners, stats, groups, teams), refactor last_matches in player_info. Optimize proxy functions. Coverage.(?) Rotating user agent (exp. till 20.05)
6
- * **0.9.0** stats & images update, more stats scrapers, team logos, player photos, images, more data, team_map stats, map stats, more functions such as get_news_id, get_team_logo, get_player_photo, get_demo_id, get_match_stats...
7
- * **0.10.0** synchronous update, reformatting the library as a synchronous, move async parser as an extension. (JULY-AUGUST 2024)
8
- * **0.11.0 - 1.0.0** Provide to use Hltv-async-api on any system, language, by creating a RESTful service.
5
+ * **0.9.0** (JUNE ?) stats & images update, more stats scrapers, team logos, player photos, images, more data, team_map stats, map stats, more functions such as get_news_id, get_team_logo, get_player_photo, get_demo_id, get_match_stats. Coverage. (?) Rotating user agent
6
+ * **0.10.0** (JULY-AUGUST 2024) synchronous update, reformatting the library as synchronous, move async parser as extension. Rename lib ?.
7
+ * **0.11.0 - 1.0.0** Provide to use Hltv-async-api on any system, language, by creating a RESTful service. (?) Classes. (?)
9
8
 
10
9
 
11
10
  # Features
@@ -6,4 +6,4 @@
6
6
  from .aiohltv import Hltv
7
7
 
8
8
  __author__ = 'akimerslys'
9
- __version__ = '0.8.2'
9
+ __version__ = '0.8.3'
@@ -3,19 +3,17 @@ import asyncio
3
3
  import re
4
4
  import logging
5
5
  import random
6
- from typing import Any, List, Optional
6
+ from typing import Any, List, Optional, Union
7
7
  from datetime import date, datetime, timedelta
8
8
  from bs4 import BeautifulSoup
9
9
  from functools import partial
10
- from aiohttp import ClientSession, ClientTimeout
11
- from aiohttp.client_exceptions import ClientProxyConnectionError, ClientResponseError, ClientOSError, \
12
- ServerDisconnectedError, ClientHttpProxyError, ClientConnectorError
10
+ from aiohttp import ClientSession
13
11
 
14
12
 
15
13
  class Hltv:
16
14
  def __init__(self,
17
- min_delay: float | int= -1.0,
18
- max_delay: float | int= 10.0,
15
+ min_delay: float | int = -1.0,
16
+ max_delay: float | int = 10.0,
19
17
  timeout: int = 5,
20
18
  max_retries: int = 10,
21
19
  proxy_path: str | None = None,
@@ -24,7 +22,7 @@ class Hltv:
24
22
  proxy_protocol: str | None = None,
25
23
  remove_proxy: bool = False,
26
24
  tz: str | None = None,
27
- safe_mode: bool = True,
25
+ safe_mode: bool = False,
28
26
  debug: bool = False,
29
27
  ):
30
28
  self.headers = {
@@ -52,17 +50,13 @@ class Hltv:
52
50
  self.PROXY_ONCE = remove_proxy
53
51
  self.PROXY_DELAY = proxy_delay
54
52
 
55
- if self.PROXY_PATH:
56
- with open(self.PROXY_PATH, "r") as file:
57
- self.PROXY_LIST = [line.strip() for line in file.readlines()]
58
-
59
- if self.PROXY_PROTOCOL:
60
- self.PROXY_LIST = [self.PROXY_PROTOCOL + '://' + proxy for i, proxy in enumerate(self.PROXY_LIST, start=0)]
61
-
62
- if proxy_path or proxy_list:
63
- self.USE_PROXY = True
64
- else:
65
- self.USE_PROXY = False
53
+ self.USE_PROXY = proxy_path or proxy_list
54
+ if self.USE_PROXY:
55
+ if self.PROXY_PATH:
56
+ with open(self.PROXY_PATH, "r") as file:
57
+ self.PROXY_LIST = [line.strip() for line in file.readlines()]
58
+ if self.PROXY_PROTOCOL:
59
+ self.PROXY_LIST = [self.PROXY_PROTOCOL + '://' + proxy for proxy in self.PROXY_LIST]
66
60
 
67
61
  self.session = None
68
62
  self.loop = asyncio.get_running_loop()
@@ -101,24 +95,25 @@ class Hltv:
101
95
  __name__,
102
96
  **{
103
97
  "level": "DEBUG" if self.DEBUG else "INFO",
104
- "format": "[%(levelname)s] %(message)s ",
98
+ "format": "[%(levelname)s] | %(message)s ",
105
99
  },
106
100
  )
107
101
 
108
- def config(self,
109
- min_delay: Optional[float | int] = None,
110
- max_delay: Optional[float | int] = None,
111
- timeout: Optional[int] = None,
112
- use_proxy: Optional[bool] = None,
113
- proxy_file_path: Optional[str] = None,
114
- proxy_list: Optional[list] = None,
115
- debug: Optional[bool] = None,
116
- max_retries: Optional[int] = None,
117
- proxy_protocol: Optional[str] = None,
118
- remove_proxy: Optional[bool] = None,
119
- tz: Optional[str] = None,
120
- safe_mode: Optional[bool] = None,
121
- ):
102
+ def config(
103
+ self,
104
+ min_delay: Optional[Union[float, int]],
105
+ max_delay: Optional[Union[float, int]],
106
+ timeout: Optional[int],
107
+ use_proxy: Optional[bool],
108
+ proxy_file_path: Optional[str],
109
+ proxy_list: Optional[List[str]],
110
+ debug: Optional[bool],
111
+ max_retries: Optional[int],
112
+ proxy_protocol: Optional[str],
113
+ remove_proxy: Optional[bool],
114
+ tz: Optional[str],
115
+ safe_mode: Optional[bool],
116
+ ) -> None:
122
117
  if min_delay or max_delay:
123
118
  self.MIN_DELAY = float(min_delay)
124
119
  self.MAX_DELAY = float(max_delay)
@@ -158,7 +153,7 @@ class Hltv:
158
153
 
159
154
  def _init_safe(self):
160
155
  if not self.SAFE:
161
- self.logger.warning('Safe mode deactivated.')
156
+ self.logger.debug('Safe mode deactivated.')
162
157
 
163
158
  def _init_delay(self):
164
159
  if self.MIN_DELAY != -1.0:
@@ -239,16 +234,10 @@ class Hltv:
239
234
  self.logger.debug(f"Error, Code {response.status=}")
240
235
  return False, await self.loop.run_in_executor(None, partial(self._parse_error_handler, delay))
241
236
 
242
- except TimeoutError as e:
243
- self.logger.debug(e)
244
-
245
- except (ClientProxyConnectionError, ClientResponseError, ClientOSError, ClientConnectorError,
246
- ServerDisconnectedError, ClientTimeout, asyncio.TimeoutError, ClientHttpProxyError) as e:
247
- self.logger.debug(e)
248
-
249
237
  except Exception as e:
250
238
  self.logger.debug(e)
251
239
 
240
+
252
241
  delay = self._parse_error_handler(delay)
253
242
  return False, delay
254
243
 
@@ -736,7 +725,7 @@ class Hltv:
736
725
  t1_id = live['team1']
737
726
  t2_id = live['team2']
738
727
 
739
- # TODO FIX SCORES
728
+ # scores will be implemented in the socket extension of this library.
740
729
  """try:
741
730
  scores = live.find("td", class_="matchTeamScore").text.strip().split('-')
742
731
  score_team1 = scores[0].strip()
@@ -870,24 +859,67 @@ class Hltv:
870
859
  return events
871
860
 
872
861
  async def get_event_info(self, event_id: str | int, event_title: str):
873
- # TODO ADD WINNER?
874
-
875
862
  r = await self._fetch(f"https://hltv.org/events/{str(event_id)}/{event_title.replace(' ', '-')}")
876
863
  if not r:
877
864
  return
878
865
 
879
- event_date_div = r.find('td', {'class', 'eventdate'}).find_all('span')
866
+ event = {'id': event_id, 'title': event_title}
880
867
 
881
- event_start = self._normalize_date(event_date_div[0].text.split())
882
- event_end = self._normalize_date(event_date_div[1].text.split()[1:-1])
868
+ def event_date_process(start_date, end_date):
869
+ current_date = datetime.now()
870
+ st = 0 # Finished
871
+ if current_date < start_date:
872
+ st = 2 # Upcoming
873
+ elif start_date <= current_date <= end_date:
874
+ st = 1 # Ongoing
883
875
 
884
- prize = r.find('td', {'class', 'prizepool text-ellipsis'}).text
876
+ return start_date.strftime('%d-%m-%Y'), end_date.strftime('%d-%m-%Y'), st
885
877
 
886
- team_num = r.find('td', {'class', 'teamsNumber'}).text
878
+ date_unix_values = [int(span.get('data-unix')[:-3])
879
+ for span in r.find('td', {'class', 'eventdate'}).find_all('span') if span.get('data-unix')]
880
+ event['start'], event['end'], event_status = event_date_process(datetime.utcfromtimestamp(date_unix_values[0]), datetime.utcfromtimestamp(date_unix_values[1]))
881
+ status_d = {0: 'Finished', 1: 'Ongoing', 2: 'Upcoming'}
882
+ event['status'] = status_d[event_status]
887
883
 
888
- location = r.find('td', {'class', 'location gtSmartphone-only'}).get_text().replace('\n', '')
884
+ event['prize'] = r.find('td', {'class', 'prizepool text-ellipsis'}).text if r.find('td', {'class', 'prizepool text-ellipsis'}).text else 'TBA'
889
885
 
890
- try:
886
+ event['team_count'] = r.find('td', {'class', 'teamsNumber'}).text if r.find('td', {'class', 'teamsNumber'}).text else 'TBA'
887
+
888
+ event['location'] = r.find('td', {'class', 'location gtSmartphone-only'}).get_text().replace('\n', '')
889
+
890
+ if event_status == 0:
891
+ try:
892
+ mvp_div = r.find('div', class_='player-and-coin').find('a')
893
+ if mvp_div:
894
+ event['mvp'] = {'id': mvp_div['href'].split('/')[2], 'nickname': mvp_div.get_text().strip()[1:-1]}
895
+ except IndexError:
896
+ pass
897
+
898
+ try:
899
+ winners_div = r.find_all('div', class_='placement')
900
+ winners = []
901
+ for i, winner in enumerate(winners_div, start=1):
902
+ team_div = winner.find('div', class_='team')
903
+ team = team_div.get_text().strip()
904
+ t_id = team_div.find('a')['href'].split('/')[2]
905
+ prize = winner.find('div', class_='prize').text
906
+ winners.append({i, team, t_id, prize})
907
+ event['winners'] = winners
908
+ except IndexError:
909
+ pass
910
+ else:
911
+ teams_div = r.find_all('div', class_='col standard-box team-box supports-hover')
912
+ teams = []
913
+ for team in teams_div:
914
+ try:
915
+ teams.append({team.find('a')['href'].split('/')[2]: team.find('div',
916
+ 'text-container').get_text().strip()}) # {id:team_name}
917
+ except IndexError:
918
+ teams.append({'?': '?'})
919
+ event['teams'] = teams
920
+
921
+ """try:
922
+ # TO BE REWROTE
891
923
  group_div = r.find('div', {'class', 'groups-container'})
892
924
  groups = []
893
925
  for group in group_div.find_all('table', {'class': 'table standard-box'}):
@@ -897,16 +929,9 @@ class Hltv:
897
929
  teams.append(team.find('a').text)
898
930
  groups.append({group_name: teams})
899
931
  except AttributeError:
900
- groups = []
932
+ groups = []"""
901
933
 
902
- return {'id': event_id,
903
- 'title': event_title,
904
- 'start': event_start,
905
- 'end': event_end,
906
- 'prize': prize,
907
- 'teams': team_num,
908
- 'location': location,
909
- 'group': groups}
934
+ return event
910
935
 
911
936
  async def get_top_teams(self, max_teams=30, date_str: str = ''):
912
937
  """
@@ -1133,7 +1158,7 @@ class Hltv:
1133
1158
  matches = []
1134
1159
  matches_div = r.find_all('div', class_='col-6 text-ellipsis')[1]
1135
1160
  for match in matches_div.find_all('a'):
1136
- matches.append(int(match['href'].split('/', 4)[3]))
1161
+ matches.append(match['href'].split('/', 4)[3])
1137
1162
 
1138
1163
  return {'id': int(id),
1139
1164
  'nickname': nickname,
@@ -1209,8 +1234,9 @@ class Hltv:
1209
1234
 
1210
1235
 
1211
1236
  async def main():
1212
- async with Hltv(debug=True, safe_mode=False, min_delay=2) as hltv:
1213
- print(await hltv.get_matches())
1237
+ async with Hltv(debug=True, safe_mode=False, min_delay=1, max_delay=1, proxy_path='proxies.txt', proxy_delay=True,
1238
+ proxy_protocol='http') as hltv:
1239
+ await hltv.get_top_players(30)
1214
1240
 
1215
1241
 
1216
1242
  if __name__ == '__main__':
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "hltv_async_api"
3
- version = "0.8.2"
3
+ version = "0.8.3"
4
4
  authors = ["Akim Slys <akimslys2003@gmail.com>"]
5
5
  description = "An unofficial asynchronous HLTV API Wrapper for Python"
6
6
  readme = "README.md"
File without changes