Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for May 2024 and various improvements #18

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 28 additions & 27 deletions kicktippbb.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""KickTipp BetBot
Automated kicktipp.de bet placement.

Places bets to the upcomming matchday.
Unless specified by parameter it places the bets on all prediction games of the account.
Places bets for the upcoming matchday.
Unless specified by parameter, it places the bets on all prediction games of the account.

Usage:
kicktippbb.py [ --get-login-token ]
Expand All @@ -12,7 +12,7 @@
Options:
COMMUNITY Name of the prediction game community to place bets on,
one or more names can be specified.
If no community name is given all available communities will be considered.
If no community name is given, all available communities will be considered.
--get-login-token Just login and print the login token string
for later use with '--use-login-token' option
--use-login-token <token> Perform bets without interactive login, use login token instead.
Expand All @@ -21,7 +21,7 @@
The duration format is <number><unit[m,h,d]>, e.g. 10m,5h or 1d
--list-predictors Display a list of predictors available to be used with '--predictor' option
--predictor <value> A specific predictor name to be used during calculation
--dry-run Dont place any bet just print out predicitons
--dry-run Don't place any bet just print out predictions
--matchday <value> Choose a specific matchday in the range of 1 to 34 to place bets on
"""

Expand All @@ -37,15 +37,15 @@
from helper.deadline import is_before_dealine, timedelta_tostring
from helper.match import Match

URL_BASE = 'http://www.kicktipp.de'
URL_BASE = 'https://www.kicktipp.de'
URL_LOGIN = URL_BASE + '/info/profil/login'

DEADLINE_REGEX = re.compile('([1-9][0-9]*)(m|h|d)')


def login(browser: RoboBrowser):
"""Log into the user account by asking for username and password.
If login succeded the login cookie token is returned
If login succeeded the login cookie token is returned
"""
while True:
username, password = get_credentials()
Expand All @@ -58,7 +58,7 @@ def login(browser: RoboBrowser):

def perform_login(browser: RoboBrowser, username: str, password: str):
"""
Open the log in page then fill out the form and submit
Open the login page then fill out the form and submit
"""
browser.open(URL_LOGIN)
form = browser.get_form()
Expand Down Expand Up @@ -92,12 +92,12 @@ def get_table_rows(soup):
return [tr.find_all('td') for tr in tbody.find_all('tr')]


def parse_match_rows(browser: RoboBrowser, community, matchday = None):
def parse_match_rows(browser: RoboBrowser, community, matchday=None):
"""Fetch latest odds for each match
Returns a list of tuples (heimtipp,gasttipp, match)
Returns a list of tuples (heimtipp, gasttipp, match)
"""
browser.open(get_tippabgabe_url(community, matchday))

content = get_kicktipp_content(browser)
rows = get_table_rows(content)

Expand All @@ -109,7 +109,7 @@ def parse_match_rows(browser: RoboBrowser, community, matchday = None):
gasttipp = row[3].find(
'input', id=lambda x: x and x.endswith('_gastTipp'))
try:
odds=[odd.replace(" ","") for odd in row[4].get_text().split("/")]
odds = [odd.replace(" ", "") for odd in row[4].get_text().replace("Quote:", "").split("/")]
match = Match(row[1].get_text(), row[2].get_text(), row[0].get_text(
), odds[0], odds[1], odds[2])
except:
Expand All @@ -122,7 +122,8 @@ def parse_match_rows(browser: RoboBrowser, community, matchday = None):

return matchtuple

def get_tippabgabe_url(community, matchday = None):

def get_tippabgabe_url(community, matchday=None):
tippabgabeurl = URL_BASE + '/' + community + '/tippabgabe'
if matchday is None:
return tippabgabeurl
Expand Down Expand Up @@ -150,15 +151,18 @@ def get_communities(browser: RoboBrowser, desired_communities: list):
browser.open(URL_BASE + '/info/profil/meinetipprunden')
content = get_kicktipp_content(browser)
links = content.find_all('a')
def gethreftext(link): return link.get('href').replace("/", "")

def gethreftext(link):
return link.get('href').replace("/", "")

def is_community(link):
hreftext = gethreftext(link)
if hreftext == link.get_text():
if hreftext == link.get_text().lower():
return True
else:
linkdiv = link.find('div', {'class': "menu-title-mit-tippglocke"})
return linkdiv and linkdiv.get_text() == hreftext
return linkdiv and linkdiv.get_text().lower() == hreftext

community_list = [gethreftext(link)
for link in links if is_community(link)]
if len(desired_communities) > 0:
Expand All @@ -185,15 +189,13 @@ def place_bets(browser: RoboBrowser, communities: list, predictor, override=Fals
input_hometeam_value = submitform[field_hometeam.attrs['name']].value
input_roadteam_value = submitform[field_roadteam.attrs['name']].value
if not override and (input_hometeam_value or input_roadteam_value):
print("{0} - skipped, already placed {1}:{2}".format(match,
input_hometeam_value, input_roadteam_value))
print("{0} - skipped, already placed {1}:{2}".format(match, input_hometeam_value, input_roadteam_value))
continue

if deadline is not None:
if not is_before_dealine(deadline, match.match_date):
time_to_match = match.match_date - datetime.datetime.now()
print("{0} - not betting yet, due in {1}".format(match,
timedelta_tostring(time_to_match)))
print("{0} - not betting yet, due in {1}".format(match, timedelta_tostring(time_to_match)))
continue

homebet, roadbet = predictor.predict(match)
Expand All @@ -216,15 +218,15 @@ def validate_arguments(arguments):


def choose_predictor(predictor_param, predictors):
if(predictor_param):
if(predictor_param in predictors):
if (predictor_param):
if (predictor_param in predictors):
predictor = predictors[predictor_param]()
else:
exit('Unknown predictor: {}'.format(predictor_param))
else:
# Just get the first predictor in the dict and instanciate it
# Just get the first predictor in the dict and instantiate it
predictor = next(iter(predictors.values()))()
print("Using predictor: "+type(predictor).__name__)
print("Using predictor: " + type(predictor).__name__)
return predictor


Expand Down Expand Up @@ -255,18 +257,17 @@ def main(arguments):
# Just use the token for all interactions with the website
browser.session.cookies['login'] = token

# Which communities are considered, fail if no were found
# Which communities are considered, fail if none were found
communities = get_communities(browser, communities)
if(len(communities) == 0):
if (len(communities) == 0):
exit("No community found!?")

# Which prediction method is used
predictor_param = arguments['--predictor'] if '--predictor' in arguments else None
predictor = choose_predictor(predictor_param, predictors_)

# Place bets
place_bets(browser, communities, predictor,
override=arguments['--override-bets'], deadline=arguments['--deadline'], dryrun=arguments['--dry-run'], matchday=arguments['--matchday'])
place_bets(browser, communities, predictor, override=arguments['--override-bets'], deadline=arguments['--deadline'], dryrun=arguments['--dry-run'], matchday=arguments['--matchday'])


if __name__ == '__main__':
Expand Down