Compare commits

...

9 Commits

Author SHA1 Message Date
5ce4c62f22 Bump version: 0.27.0 → 0.27.1 2021-10-23 16:32:22 +03:00
b80fa43e99 Updates 2021-10-23 16:30:04 +03:00
62f53c0396 Short Maintenance message 2021-10-23 16:19:00 +03:00
051d4765a4 Correct sleeping if no energy 2021-10-23 16:19:00 +03:00
365ad9a719 Send state update and let the bg task live even if Captcha is required 2021-10-23 16:19:00 +03:00
81f00bdbf6 Create codeql-analysis.yml 2021-10-23 16:16:40 +03:00
44d221ac1b Merge branch 'master' of github.com:eeriks/erepublik 2021-10-23 16:16:17 +03:00
e4814cfa8e updates 2021-08-18 10:40:19 +03:00
ba336fe8ed Zero medal reward update 2021-08-18 09:28:00 +03:00
6 changed files with 128 additions and 54 deletions

71
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '16 0 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@ -4,7 +4,7 @@
__author__ = """Eriks Karls"""
__email__ = "eriks@72.lv"
__version__ = "0.27.0"
__version__ = "0.27.1"
from erepublik.citizen import Citizen

View File

@ -187,15 +187,15 @@ class CitizenBaseAPI:
) -> Response:
c = [cookie.name for cookie in self._req.cookies if not cookie.has_nonstandard_attr("HttpOnly")]
env = dict(l=["tets"], s=[], c=c, m=0)
cookies = dict(
sh=hashlib.sha256(",".join(env["l"] + env["s"]).encode("utf8")).hexdigest(),
ch=hashlib.sha256(",".join(env["c"]).encode("utf8")).hexdigest(),
)
session_hash = hashlib.sha256(",".join(env["l"] + env["s"]).encode("utf8")).hexdigest()
cookies_hash = hashlib.sha256(",".join(env["c"]).encode("utf8")).hexdigest()
cookie_kwargs = dict(
expires=int(time.time()) + 120, path="/en/main/sessionUnlock", domain=".www.erepublik.com", secure=True, rest={"HttpOnly": True}
)
self._req.cookies.set("sh", cookies["sh"], **cookie_kwargs)
self._req.cookies.set("ch", cookies["ch"], **cookie_kwargs)
self._req.cookies.set("sh", session_hash, **cookie_kwargs)
self._req.cookies.set("ch", cookies_hash, **cookie_kwargs)
b64_env = utils.b64json(env)
data = dict(
_token=self.token,

View File

@ -7,7 +7,7 @@ from decimal import Decimal
from itertools import product
from threading import Event
from time import sleep
from typing import Any, Dict, List, NoReturn, Optional, Set, Tuple, Union
from typing import Any, Dict, List, NoReturn, Optional, Set, Tuple, TypedDict, Union
from requests import HTTPError, RequestException, Response
@ -193,8 +193,8 @@ class BaseCitizen(access_points.CitizenAPI):
if kind not in self.promos:
self.reporter.report_promo(kind, time_until)
self.promos[kind] = time_until
except Exception:
self.process_error()
except Exception: # noqa
self.report_error()
new_date = re.search(r"var new_date = '(\d*)';", html)
if new_date:
self.energy.set_reference_time(utils.good_timedelta(self.now, timedelta(seconds=int(new_date.group(1)))))
@ -279,20 +279,22 @@ class BaseCitizen(access_points.CitizenAPI):
return self._post_main_session_get_challenge(captcha_id, image_id).json()
def solve_captcha(self, src: str) -> Optional[List[Dict[str, int]]]:
class _API_RESULT(dict):
class ApiResult(TypedDict):
x: int
y: int
class _API_RETURN(dict):
class ApiReturn(TypedDict):
status: bool
message: str
result: Optional[List[_API_RESULT]]
result: Optional[List[ApiResult]]
solve_data: _API_RETURN = self.post(
"https://api.erep.lv/captcha/api", data=dict(citizen_id=self.details.citizen_id, src=src, key="CaptchaDevAPI")
).json()
solve_data = ApiReturn(
**self.post(
"https://api.erep.lv/captcha/api", data=dict(citizen_id=self.details.citizen_id, src=src, password="CaptchaDevAPI")
).json()
)
if solve_data["status"]:
return solve_data.get("result")
return solve_data["result"]
@property
def inventory(self) -> classes.Inventory:
@ -479,12 +481,8 @@ class BaseCitizen(access_points.CitizenAPI):
else:
icon = "//www.erepublik.net/" + item_data["icon"]
raw_materials[constants.INDUSTRIES[item_data.get("industryId")]].update(
{
0: dict(
name=item_data.get("name"), amount=item_data["amount"] + (item_data.get("underCostruction", 0) / 100), icon=icon
)
}
raw_materials[constants.INDUSTRIES[item_data.get("industryId")]][0] = dict(
name=item_data.get("name"), amount=item_data["amount"] + (item_data.get("underCostruction", 0) / 100), icon=icon
)
offers: Dict[str, Dict[int, Dict[str, Union[str, int]]]] = {}
@ -792,7 +790,7 @@ class BaseCitizen(access_points.CitizenAPI):
reward = reward[:-1]
if (title, reward) not in data:
data[(title, reward)] = dict(about=about, kind=title, reward=reward, count=1, currency=currency)
data[(title, reward)] = dict(about=about, kind=title, reward=reward or 0, count=1, currency=currency)
else:
data[(title, reward)]["count"] += 1
except AttributeError:
@ -874,7 +872,7 @@ class BaseCitizen(access_points.CitizenAPI):
if re.search(
r"Occasionally there are a couple of things which we need to check or to implement in order make "
r"your experience in eRepublik more pleasant. <strong>Don\'t worry about ongoing battles, timer "
r"will be stopped during maintenance.</strong>",
r"will be stopped during maintenance.</strong>|Maintenance. We&rsquo;ll be back any second now.",
response.text,
):
self.write_warning("eRepublik is having maintenance. Sleeping for 5 mi#nutes")
@ -1597,6 +1595,12 @@ class CitizenEconomy(CitizenTravel):
if self.config.telegram:
self.telegram.report_item_donation(citizen_id, amount, f"{industry} q{quality}")
def _update_inventory_data(self, *args, **kwargs):
super()._update_inventory_data(*args, **kwargs)
if self.food["total"] < 240 * self.energy.interval:
self.buy_food()
class CitizenLeaderBoard(BaseCitizen):
def get_aircraft_damage_rankings(self, country: int, weeks: int = 0, mu: int = 0) -> Dict[str, any]:
@ -2002,7 +2006,7 @@ class CitizenMilitary(CitizenTravel):
energy_used = 0
if deployment_id:
self.write_warning(
"If erepublik responds with HTTP 500 Internal Error, it is kind of ok, because deployment has not finished yet."
"If eRepublik responds with HTTP 500 Internal Error, it is kind of ok, because deployment has not finished yet."
)
deployment_data = self._post_military_fight_deploy_deploy_report_data(deployment_id).json()
if not deployment_data.get("error"):
@ -2305,7 +2309,7 @@ class CitizenMilitary(CitizenTravel):
type="damage",
)
r_json = r.json()
return (r_json.get(str(battle.invader.id)).get("fighterData"), r_json.get(str(battle.defender.id)).get("fighterData"))
return r_json.get(str(battle.invader.id)).get("fighterData"), r_json.get(str(battle.defender.id)).get("fighterData")
def get_battle_division_stats(self, division: classes.BattleDivision) -> Dict[str, Any]:
battle = division.battle
@ -2625,10 +2629,9 @@ class CitizenTasks(CitizenEconomy):
else:
self.reporter.report_action("WORK", json_val=js)
else:
if self.energy.food_fights < 1:
seconds = (self.energy.reference_time - self.now).total_seconds()
self.write_warning(f"I don't have energy to work. Will sleep for {seconds}s")
self.sleep(seconds)
seconds = self.now.timestamp() % 360
self.write_warning(f"I don't have energy to work. Will sleep for {seconds}s")
self.sleep(seconds)
self.work()
def train(self):
@ -2652,11 +2655,9 @@ class CitizenTasks(CitizenEconomy):
else:
self.reporter.report_action("TRAIN", response.json())
else:
if self.energy.food_fights < len(tgs):
large = max(self.energy.reference_time, self.now)
sleep_seconds = utils.get_sleep_seconds(large)
self.write_warning(f"I don't have energy to train. Will sleep for {sleep_seconds} seconds")
self.sleep(sleep_seconds)
seconds = self.now.timestamp() % 360
self.write_warning(f"I don't have energy to train. Will sleep for {seconds}s")
self.sleep(seconds)
self.train()
def work_ot(self):
@ -2674,11 +2675,9 @@ class CitizenTasks(CitizenEconomy):
self.buy_food(120)
self.reporter.report_action("WORK_OT", r.json())
elif self.energy.food_fights < 1 and self.ot_points >= 24:
if self.energy.food_fights < 1:
large = max(self.energy.reference_time, self.now)
sleep_seconds = utils.get_sleep_seconds(large)
self.write_warning(f"I don't have energy to work OT. Will sleep for {sleep_seconds}s")
self.sleep(sleep_seconds)
seconds = self.now.timestamp() % 360
self.write_warning(f"I don't have energy to work OT. Will sleep for {seconds}s")
self.sleep(seconds)
self.work_ot()
def resign_from_employer(self) -> bool:
@ -2800,15 +2799,18 @@ class _Citizen(
if award_id and title and medal.get("details").get("isWallMaterial"):
self._post_main_wall_post_automatic(title.lower(), award_id)
if params.get("ccValue"):
reward = params.get("ccValue")
if "ccValue" in params:
reward = params.get("ccValue") or 0
currency = "Currency"
elif params.get("goldValue"):
reward = params.get("goldValue")
elif "goldValue" in params:
reward = params.get("goldValue") or 0
currency = "Gold"
else:
reward = params.get("energyValue")
elif "energyValue" in params:
reward = params.get("energyValue") or 0
currency = "Energy"
else:
reward = 0
currency = "Unknown"
if (title, reward) not in data:
data[(title, reward)] = {
@ -2845,8 +2847,8 @@ class _Citizen(
self.update_companies()
self.update_money()
self.update_weekly_challenge()
self.send_state_update()
self.check_for_notification_medals()
self.send_state_update()
def update_weekly_challenge(self):
data = self._get_main_weekly_challenge_data().json()
@ -2911,11 +2913,12 @@ class _Citizen(
start_time = utils.good_timedelta(start_time.replace(minute=0), timedelta(hours=1))
while not self.stop_threads.is_set():
start_time = utils.good_timedelta(start_time, timedelta(minutes=10 if self.restricted_ip else 30))
self.update_citizen_info()
self.update_weekly_challenge()
self.send_state_update()
try:
self.update_all()
except classes.CaptchaSessionError:
self.send_state_update()
pass
self.send_inventory_update()
self.update_companies()
self.send_my_companies_update()
sleep_seconds = (start_time - self.now).total_seconds()
self.stop_threads.wait(sleep_seconds if sleep_seconds > 0 else 0)

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.27.0
current_version = 0.27.1
commit = True
tag = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\.?(?P<dev>\d+)?

View File

@ -50,6 +50,6 @@ setup(
test_suite="tests",
tests_require=test_requirements,
url="https://github.com/eeriks/erepublik/",
version="0.27.0",
version="0.27.1",
zip_safe=False,
)