-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Drop support for qzone web apis (#134)
* build(deps): aioqzone v1.1.0 * refactor(api)!: remove web api * test(refactor)!: remove qzone web apis --------- Co-authored-by: JamzumSum <[email protected]>
- Loading branch information
1 parent
39de0e9
commit b16cd53
Showing
18 changed files
with
853 additions
and
1,259 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
[tool.poetry] | ||
name = "aioqzone-feed" | ||
version = "0.14.2.dev1" | ||
description = "aioqzone plugin providing higher level api for processing feed." | ||
version = "1.0.0.dev1" | ||
description = "aioqzone plugin that provides higher level apis for processing feeds." | ||
authors = ["aioqzone <[email protected]>"] | ||
license = "AGPL-3.0" | ||
readme = "README.md" | ||
|
@@ -15,13 +15,11 @@ documentation = "https://aioqzone.github.io/aioqzone-feed" | |
[tool.poetry.dependencies] | ||
python = "^3.8" | ||
aioqzone = [ | ||
{ version = "^0.14.4.dev1", allow-prereleases = true }, | ||
{ version = "^0.14.4.dev1", allow-prereleases = true, extras = [ | ||
{ version = "^1.1.0.dev1", allow-prereleases = true }, | ||
{ version = "^1.1.0.dev1", allow-prereleases = true, extras = [ | ||
"captcha", | ||
], optional = true }, | ||
] | ||
exceptiongroup = { version = ">=1.1.1", python = "<3.11" } | ||
lxml = "^4.9.1" | ||
|
||
[tool.poetry.extras] | ||
captcha = ["aioqzone"] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
from .feed import FeedApi | ||
from .feed import FeedH5Api as FeedApi | ||
from .heartbeat import HeartbeatApi | ||
|
||
__all__ = ["FeedApi", "HeartbeatApi"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import logging | ||
import time | ||
import typing as t | ||
|
||
from aioqzone.model import FeedData | ||
|
||
from aioqzone_feed.api.heartbeat import HeartbeatApi | ||
from aioqzone_feed.message import FeedApiEmitterMixin | ||
from aioqzone_feed.type import FeedContent | ||
|
||
log = logging.getLogger(__name__) | ||
MAX_BID = 0x7FFF | ||
"""The max batch id. | ||
.. versionadded:: 0.14.1 | ||
""" | ||
|
||
|
||
class FeedH5Api(FeedApiEmitterMixin, HeartbeatApi): | ||
""" | ||
.. versionadded:: 0.13.0 | ||
""" | ||
|
||
bid = 0 | ||
|
||
def new_batch(self) -> int: | ||
""" | ||
The new_batch function edit internal batch id and return it. | ||
A batch id can be used to identify a batch, thus even the same feed can have different id e.g. `(bid, uin, abstime)`. | ||
:return: The batch_id. | ||
""" | ||
|
||
self.bid = (self.bid + 1) % MAX_BID | ||
return self.bid | ||
|
||
async def _get_feeds_by_pred( | ||
self, | ||
stop_pred: t.Callable[[FeedData, int], bool], | ||
filter_pred: t.Optional[t.Callable[[FeedData], bool]] = None, | ||
): | ||
""" | ||
:meta public: | ||
:return: number of feeds that we have fetched actually. | ||
:raise `tenacity.RetryError`: Exception from :meth:`.get_active_feeds`. | ||
.. note:: You may need :meth:`.new_batch` to generate a new batch id. | ||
""" | ||
stop_fetching = False | ||
attach_info = "" | ||
cnt_got = 0 | ||
|
||
while not stop_fetching: | ||
resp = await self.get_active_feeds(attach_info) | ||
attach_info = resp.attachinfo | ||
feeds = resp.vFeeds | ||
stop_fetching = not resp.hasmore | ||
|
||
log.debug(attach_info, extra=dict(got=cnt_got)) | ||
|
||
for fd in feeds: | ||
if filter_pred and filter_pred(fd): | ||
continue | ||
if stop_pred(fd, cnt_got) or await self.stop_fetch(fd): | ||
stop_fetching = True | ||
continue | ||
cnt_got += 1 | ||
self._dispatch_feed(fd) | ||
|
||
return cnt_got | ||
|
||
async def get_feeds_by_count(self, count: int = 10) -> int: | ||
"""Get feeds by count. | ||
:param count: feeds count to get, max as 10, defaults to 10 | ||
.. seealso:: :meth:`._get_feeds_by_pred`. | ||
""" | ||
if count <= 0: | ||
return 0 | ||
count = min(count, 10) | ||
return await self._get_feeds_by_pred(lambda _, cnt: cnt >= count) | ||
|
||
async def get_feeds_by_second( | ||
self, | ||
seconds: float, | ||
start: t.Optional[float] = None, | ||
) -> int: | ||
"""Get feeds by abstime (seconds). Range: [`start` - `seconds`, `start`]. | ||
:param seconds: filter on abstime, calculate from `start`. | ||
:param start: start timestamp, defaults to None, means now. | ||
.. seealso:: :meth:`._get_feeds_by_pred`. | ||
""" | ||
if seconds <= 0: | ||
return 0 | ||
|
||
start = start or time.time() | ||
end = start - seconds | ||
|
||
if end > time.time(): | ||
return 0 | ||
|
||
return await self._get_feeds_by_pred( | ||
lambda feed, _: feed.abstime < end, lambda feed: feed.abstime > start | ||
) | ||
|
||
def drop_rule(self, feed: FeedData) -> bool: | ||
"""Drop feeds according to some rules. | ||
No need to emit :meth:`FeedEvent.FeedDropped` event, it is handled by :meth:`_dispatch_feed`. | ||
Subclasses may inherit this method to customize their own rules. | ||
:param feed: the feed | ||
:return: if the feed is dropped. | ||
""" | ||
if feed.userinfo.uin == 20050606: | ||
log.info(f"advertisement rule hit: {feed.userinfo.uin}") | ||
log.debug(f"Dropped: {feed}") | ||
return True | ||
|
||
if feed.fid.startswith("advertisement"): | ||
log.info(f"advertisement rule hit: {feed.fid}") | ||
log.debug(f"Dropped: {feed}") | ||
return True | ||
|
||
return False | ||
|
||
def _dispatch_feed(self, feed: FeedData) -> None: | ||
"""dispatch feed according to api support. | ||
1. Drop feed according to rules defined in `drop_rule`, trigger :meth:`FeedDropped` hook if dropped; | ||
2. Get more if `hasmore` flag is set to ``1`` (Not Implemented yet); | ||
3. Trigger :meth:`FeedProcEnd` for prcocessed feeds. | ||
:param feed: feed | ||
""" | ||
if feed.summary.hasmore: | ||
self.ch_feed_dispatch.add_awaitable( | ||
self.shuoshuo(feed.fid, feed.userinfo.uin, feed.common.appid) | ||
).add_done_callback(lambda t: self._dispatch_feed(t.result())) | ||
return | ||
|
||
model = FeedContent.from_feed(feed) | ||
|
||
if self.drop_rule(feed): | ||
FeedContent.from_feed(feed) | ||
self.ch_feed_dispatch.add_awaitable(self.feed_dropped.results(self.bid, model)) | ||
return | ||
|
||
model.set_detail(feed) | ||
self.ch_feed_notify.add_awaitable(self.feed_processed.results(self.bid, model)) | ||
|
||
def stop(self) -> None: | ||
"""Clear **all** registered tasks. All tasks will be CANCELLED if not finished.""" | ||
log.warning("FeedApi stopping...") | ||
FeedApiEmitterMixin.stop(self) | ||
HeartbeatApi.stop(self) |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.