forked from prostomarkeloff/vkwave
-
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.
Merge branch 'master' of github.com:fscdev/vkwave
- Loading branch information
Showing
16 changed files
with
681 additions
and
0 deletions.
There are no files selected for viewing
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,56 @@ | ||
from vkwave.api.methods import APIOptionsRequestContext | ||
from vkwave.bots.easy import SimpleLongPollBot, TaskManager | ||
from vkwave.vkscript import execute | ||
from vkwave.types.responses import ExecuteResponse | ||
|
||
bot = SimpleLongPollBot( | ||
tokens=["123"], | ||
group_id=456, | ||
) | ||
|
||
|
||
@execute | ||
def get_subs_names(api: APIOptionsRequestContext, group_id: int): | ||
subs_names = [] | ||
|
||
subscribers = api.groups.getMembers(group_id=group_id) | ||
subscribers = subscribers.items | ||
|
||
for sub_id in subscribers: | ||
subscriber_data = api.users.get(user_ids=sub_id) | ||
subs_names.append(subscriber_data[0].first_name) | ||
|
||
return subs_names | ||
|
||
|
||
@bot.message_handler(bot.text_filter("follow")) | ||
async def simple(event: bot.BaseEvent): | ||
""" | ||
Get name of each subscriber | ||
""" | ||
|
||
check_group = 191949777 | ||
|
||
print(get_subs_names.build(api=event.api_ctx, group_id=check_group)) | ||
""" | ||
var subs_names=[]; | ||
var subscribers=API.groups.getMembers({group_id:1}); | ||
var subscribers=subscribers.items; | ||
while(subscribers.length > 0){ | ||
var sub_id=subscribers.pop(); | ||
var subscriber_data=API.users.get({user_ids:sub_id}); | ||
subs_names.push(subscriber_data[0].first_name); | ||
}; | ||
return subs_names; | ||
""" | ||
|
||
execute_data: ExecuteResponse = await get_subs_names(api=event.api_ctx, group_id=check_group) | ||
print(execute_data) | ||
await event.api_ctx.messages.send( | ||
peer_id=event.object.object.message.peer_id, message=execute_data.response, random_id=0, | ||
) | ||
|
||
|
||
tm = TaskManager() | ||
tm.add_task(bot.run) | ||
tm.run() |
Empty file.
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,160 @@ | ||
import string | ||
|
||
import pytest | ||
|
||
from vkwave.vkscript import execute | ||
|
||
TEST_STRING = string.printable | ||
|
||
|
||
@execute | ||
def demo_build(): | ||
pass | ||
|
||
|
||
def test_build(): | ||
code = demo_build.build() | ||
assert code == "" | ||
|
||
|
||
@execute | ||
def demo_assignments(): | ||
test = 0 | ||
test = TEST_STRING | ||
test = () | ||
test = [] | ||
test = {} | ||
test = True | ||
test = False | ||
test = None | ||
tmp = [0, TEST_STRING, (), [], {}] | ||
test = tmp | ||
del test, tmp | ||
|
||
# Augmented Assignments | ||
test = 0 | ||
test += 1 | ||
test -= 1 | ||
test /= 1 | ||
test *= 1 | ||
test >>= 1 | ||
test <<= 1 | ||
test **= 1 | ||
test |= 1 | ||
test &= 1 | ||
test %= 1 | ||
del test | ||
|
||
|
||
@execute | ||
def demo_functions(): | ||
test = [0, 1, 3, 4] | ||
tmp = test[0:2] | ||
end = test.pop() | ||
begin = test.shift() | ||
test.unshift(begin) | ||
test.append(end) | ||
test.splice(1, 2, 3, 3) | ||
test = "aba" | ||
test.split("b") | ||
test.substr(1, 2) | ||
|
||
|
||
@execute | ||
def demo_blocks(): | ||
test = [] | ||
i = 1 | ||
while i <= 10: | ||
test.append(i) | ||
i += 1 | ||
|
||
if len(test) == 10: | ||
return "ok" | ||
elif i == 1: | ||
return "oops..." | ||
else: | ||
return "oops..." | ||
|
||
|
||
def test_converter(): | ||
assignments = demo_assignments.build() | ||
functions = demo_functions.build() | ||
blocks = demo_blocks.build() | ||
assert assignments == ( | ||
"var test=0;" | ||
f"var test={repr(TEST_STRING)};" | ||
"var test=[];" | ||
"var test=[];" | ||
"var test={};" | ||
"var test=true;" | ||
"var test=false;" | ||
"var test=null;" | ||
f"var tmp=[0,{repr(TEST_STRING)},[],[],{{}}];" | ||
"var test=tmp;" | ||
"delete test;" | ||
"delete tmp;" | ||
"var test=0;" | ||
"test=test+(1);" | ||
"test=test-(1);" | ||
"test=test/(1);" | ||
"test=test*(1);" | ||
"test=test>>(1);" | ||
"test=test<<(1);" | ||
"test=test**(1);" | ||
"test=test|(1);" | ||
"test=test&(1);" | ||
"test=test%(1);" | ||
"delete test;" | ||
) | ||
assert functions == ( | ||
"var test=[0,1,3,4];" | ||
"var tmp=test.slice(0,2);" | ||
"var end=test.pop();" | ||
"var begin=test.shift();" | ||
"test.unshift(begin);" | ||
"test.push(end);" | ||
"test.splice(1,2,3,3);" | ||
"var test='aba';" | ||
"test.split('b');" | ||
"test.substr(1,2);" | ||
) | ||
assert blocks == ( | ||
"var test=[];" | ||
"var i=1;" | ||
"while(i<=10){" | ||
"test.push(i);" | ||
"i=i+(1);" | ||
"};" | ||
"if(test.length==10){" | ||
"return 'ok';" | ||
"}else{" | ||
"if(i==1){" | ||
"return 'oops...';" | ||
"}else{" | ||
"return 'oops...';" | ||
"};" | ||
"};" | ||
) | ||
|
||
|
||
@execute | ||
def demo_args(x, y): | ||
i = x | ||
i *= y | ||
return i | ||
|
||
|
||
@execute | ||
def demo_preprocessor(x, y): | ||
return x + y * x | ||
|
||
|
||
@demo_preprocessor.preprocessor | ||
async def preprocessor(x, y): | ||
return demo_preprocessor.build(x, y + 1) | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_execute(): | ||
assert demo_args.build(10, 20) == "var i=10;i=i*(20);return i;" | ||
assert await demo_preprocessor(7, 3) == "return 7+4*7;" |
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
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,13 @@ | ||
from ._category import Category | ||
from vkwave.types.responses import ExecuteResponse | ||
|
||
|
||
class Execute(Category): | ||
async def __call__(self, code: str, return_raw_response: bool = False): | ||
|
||
raw_result = await self.api_request("", {"code": code}) | ||
if return_raw_response: | ||
return raw_result | ||
|
||
result = ExecuteResponse(**raw_result) | ||
return result |
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
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,7 @@ | ||
import vkwave.vkscript.handlers.statements | ||
from .converter import VKScriptConverter | ||
from .execute import Execute | ||
from .execute import execute | ||
|
||
|
||
__all__ = ("execute", "Execute", "VKScriptConverter") |
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,58 @@ | ||
import typing | ||
import contextvars | ||
|
||
import pydantic | ||
|
||
from typing import Type | ||
from typing import TypeVar | ||
|
||
|
||
T = TypeVar("T") | ||
|
||
|
||
class ContextInstanceMixin: | ||
def __init_subclass__(cls, **kwargs): | ||
cls.__context_instance = contextvars.ContextVar("instance_" + cls.__name__) | ||
return cls | ||
|
||
@classmethod | ||
def get_current(cls: Type[T], no_error=True) -> T: | ||
if no_error: | ||
return cls.__context_instance.get(None) | ||
return cls.__context_instance.get() | ||
|
||
@classmethod | ||
def set_current(cls: Type[T], value: T): | ||
if not isinstance(value, cls): | ||
raise TypeError( | ||
f"Value should be instance of '{cls.__name__}' not '{type(value).__name__}'" | ||
) | ||
cls.__context_instance.set(value) | ||
|
||
|
||
class Scope(pydantic.BaseModel): | ||
locals: list = [] | ||
globals: dict = {} | ||
|
||
|
||
class VKScriptConverter(ContextInstanceMixin): | ||
handlers: dict = {} | ||
|
||
@classmethod | ||
def register(cls, expr): | ||
def meta(handler: typing.Callable): | ||
cls.handlers[expr] = handler | ||
|
||
return meta | ||
|
||
def __init__(self, scope: Scope = None): | ||
self.scope = scope or Scope() | ||
self.set_current(self) | ||
|
||
def convert_node(self, node): | ||
if node.__class__ in self.handlers: | ||
return self.handlers[node.__class__](node) | ||
raise NotImplementedError(f"Conversion for type {node.__class__} not implemented.") | ||
|
||
def convert_block(self, nodes: list): | ||
return "".join(self.convert_node(child) for child in nodes) |
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,55 @@ | ||
import ast | ||
import inspect | ||
import types | ||
|
||
from vkwave.api.methods import APIOptionsRequestContext | ||
from vkwave.vkscript import Scope | ||
from vkwave.vkscript import VKScriptConverter | ||
|
||
|
||
def execute(func: types.FunctionType): | ||
e = Execute() | ||
return e.decorate(func) | ||
|
||
|
||
class Execute: | ||
_code = None | ||
_preprocessor = None | ||
_func = None | ||
|
||
def decorate(self, func): | ||
source = inspect.getsource(func) | ||
self._func = func | ||
self._code = ast.parse(source).body[0] | ||
return self | ||
|
||
def preprocessor(self, func): | ||
self._preprocessor = func | ||
|
||
def build(self, *args, **kwargs) -> str: | ||
if self._code.__class__ == ast.FunctionDef: | ||
globals_ = dict(self._func.__globals__) | ||
for i, argument in enumerate(self._code.args.args): | ||
if argument.arg in kwargs: | ||
globals_[argument.arg] = kwargs[argument.arg] | ||
elif i < len(args): | ||
globals_[argument.arg] = args[i] | ||
elif argument.arg.upper() == "API": | ||
continue | ||
else: | ||
raise TypeError(f"missing required argument {argument.arg}") | ||
converter = VKScriptConverter(Scope(globals=globals_)) | ||
return converter.convert_block(self._code.body) | ||
raise NotImplementedError() | ||
|
||
async def __call__(self, *args, **kwargs): | ||
if self._preprocessor is not None: | ||
return await self._preprocessor(*args, **kwargs) | ||
return await self.execute(*args, **kwargs) | ||
|
||
async def execute(self, api: APIOptionsRequestContext, *args, **kwargs): | ||
code = self.build(*args, **kwargs) | ||
response = await api.execute(code=code) | ||
return response | ||
|
||
e = execute |
Empty file.
Oops, something went wrong.