diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 0000000..0d5d518 --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,27 @@ +name: Testing Workflow +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + testing: + runs-on: macos-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: 1.23.1 + - name: Run golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.61 + - name: Run tests + run: go test -v ./... + env: + GROUP_ID: ${{ secrets.GROUP_ID }} + GROUP_TOKEN: ${{ secrets.GROUP_TOKEN }} + USER_TOKEN: ${{ secrets.USER_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f66d762 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.idea +/.vscode \ No newline at end of file diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..d2dc383 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,83 @@ +run: + timeout: 5m + +linters-settings: + depguard: + rules: + main: + allow: + - net/http + - net/url + - io + - log + - context + - bytes + - mime/multipart + - strings + - time + - sync + - errors + - fmt + - encoding/json + - encoding/msgpack + - os + - strconv + - testing + - go.uber.org/zap + - github.com/stretchr/testify + - github.com/botscommunity/botsgo + - github.com/aejoy/vkgo + - github.com/SevereCloud/vksdk + - github.com/gofiber/fiber/v2 + lll: + line-length: 200 + +linters: + disable-all: true + enable: + - asciicheck + - bodyclose + - depguard + - dogsled + - dupl + - errcheck + - copyloopvar + - funlen + - gochecknoglobals + - gocheckcompilerdirectives + - gochecknoinits + - gocognit + - goconst + - gocritic + - gocyclo + - godot + - godox + - err113 + - gofmt + - goimports + - mnd + - goprintffuncname + - gosec + - gosimple + - govet + - ineffassign + - lll + - misspell + - nakedret + - nestif + - noctx + - nolintlint + - prealloc + - predeclared + - revive + - staticcheck + - stylecheck + - testpackage + - thelper + - tparallel + - typecheck + - unconvert + - unparam + - unused + - whitespace + - wsl diff --git a/CONTACTS.md b/CONTACTS.md new file mode 100644 index 0000000..8897094 --- /dev/null +++ b/CONTACTS.md @@ -0,0 +1,3 @@ +# Contacting bot developers + +If users do not respond, you can always contact the founders of this library in [VK](https://vk.com/shizumico) or [Telegram](https://t.me/shizumico), who will try to solve your problem. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..1d152c6 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,137 @@ +# Contributing to CONTRIBUTING.md + +First off, thanks for taking the time to contribute! ❤️ + +All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉 + +> And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about: +> - Star the project +> - Tweet about it +> - Refer this project in your project's readme +> - Mention the project at local meetups and tell your friends/colleagues + + +## Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [I Have a Question](#i-have-a-question) +- [I Want To Contribute](#i-want-to-contribute) +- [Reporting Bugs](#reporting-bugs) +- [Suggesting Enhancements](#suggesting-enhancements) +- [Your First Code Contribution](#your-first-code-contribution) +- [Improving The Documentation](#improving-the-documentation) +- [Styleguides](#styleguides) +- [Commit Messages](#commit-messages) +- [Join The Project Team](#join-the-project-team) + + +## Code of Conduct + +This project and everyone participating in it is governed by the +[CONTRIBUTING.md Code of Conduct](blob/master/CODE_OF_CONDUCT.md). +By participating, you are expected to uphold this code. Please report unacceptable behavior +to <>. + + +## I Have a Question + +> If you want to ask a question, we assume that you have read the available [Documentation](). + +Before you ask a question, it is best to search for existing [Issues](/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first. + +If you then still feel the need to ask a question and need clarification, we recommend the following: + +- Open an [Issue](/issues/new). +- Provide as much context as you can about what you're running into. +- Provide project and platform versions (nodejs, npm, etc), depending on what seems relevant. + +We will then take care of the issue as soon as possible. + + + +## I Want To Contribute + +> ### Legal Notice +> When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license. + +### Reporting Bugs + + +#### Before Submitting a Bug Report + +A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible. + +- Make sure that you are using the latest version. +- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](). If you are looking for support, you might want to check [this section](#i-have-a-question)). +- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](issues?q=label%3Abug). +- Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue. +- Collect information about the bug: +- Stack trace (Traceback) +- OS, Platform and Version (Windows, Linux, macOS, x86, ARM) +- Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant. +- Possibly your input and the output +- Can you reliably reproduce the issue? And can you also reproduce it with older versions? + + +#### How Do I Submit a Good Bug Report? + +> You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public. Instead sensitive bugs must be sent by email to <>. + + +We use GitHub issues to track bugs and errors. If you run into an issue with the project: + +- Open an [Issue](/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.) +- Explain the behavior you would expect and the actual behavior. +- Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case. +- Provide the information you collected in the previous section. + +Once it's filed: + +- The project team will label the issue accordingly. +- A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Bugs with the `needs-repro` tag will not be addressed until they are reproduced. +- If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be [implemented by someone](#your-first-code-contribution). + + + + +### Suggesting Enhancements + +This section guides you through submitting an enhancement suggestion for CONTRIBUTING.md, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions. + + +#### Before Submitting an Enhancement + +- Make sure that you are using the latest version. +- Read the [documentation]() carefully and find out if the functionality is already covered, maybe by an individual configuration. +- Perform a [search](/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. +- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library. + + +#### How Do I Submit a Good Enhancement Suggestion? + +Enhancement suggestions are tracked as [GitHub issues](/issues). + +- Use a **clear and descriptive title** for the issue to identify the suggestion. +- Provide a **step-by-step description of the suggested enhancement** in as many details as possible. +- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you. +- You may want to **include screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux. +- **Explain why this enhancement would be useful** to most CONTRIBUTING.md users. You may also want to point out the other projects that solved it better and which could serve as inspiration. + + + +### Your First Code Contribution + + +### Improving The Documentation + + +## Styleguides +### Commit Messages + + +## Join The Project Team + + + +## Attribution +This guide is based on the **contributing.md**. [Make your own](https://contributing.md/)! diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ca111b5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 BotsCommunity + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..87f40c8 --- /dev/null +++ b/README.md @@ -0,0 +1,57 @@ +Bots Community + +

Flexible and high-performance VK API module Go

+ +
+ + + + + + + + + +
+ +

Instalation

+ +```bash +go get github.com/aejoy/vkgo +``` + +

Getting started

+ +Examples of working bots can be seen in the catalog [/samples](./samples) + +A simple example of a LongPoll API Bot: + +```go +package main + +import ( + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/longpoll" + "github.com/aejoy/vkgo/scene" + "github.com/aejoy/vkgo/update" + "log" + "os" +) + +func main() { + bot, err := api.NewBot(os.Getenv("TOKEN")) + if err != nil { /* ... */ + } + + messages := scene.OnMessage(func(bot *api.API, message update.Message) { + bot.SendMessage(message.ChatID, message.Text) + }) + + log.Fatalln(longpoll.Start(bot, messages)) +} + +``` + +

Help in solving problems

+ +Don't know how to solve your problem? Ask the programmers from [our community](./CONTACTS.md). There is a chance that they have already dealt with this problem and are ready to help you \ No newline at end of file diff --git a/api/README.md b/api/README.md new file mode 100644 index 0000000..781c5ee --- /dev/null +++ b/api/README.md @@ -0,0 +1,202 @@ +# Методы + +## Account + +| Метод API | Метод библиотеки | Состояние | +|---------------------------|-------------------|-----------| +| account.ban | Ban | ✅ | +| account.changePassword | ChangePassword | ✅ | +| account.getActiveOffers | GetActiveOffers | ✅ | +| account.getAppPermissions | GetAppPermissions | ✅ | +| account.getBanned | GetBans | ✅ | +| account.getCounters | GetCounters | ✅ | +| account.getInfo | GetInfo | ✅ | +| account.getProfileInfo | GetProfileInfo | ✅ | +| account.getPushSettings | GetPushSettings | ❌ | +| account.lookupContacts | | 🚾 | +| account.registerDevice | | ❌ | +| account.saveProfileInfo | EditProfileInfo | ✅ | +| account.setInfo | EditInfo | ✅ | +| account.setNameInMenu | | 🚾 | +| account.setOffline | SetOffline | ✅ | +| account.setOnline | SetOnline | ✅ | +| account.setPushSettings | | ❌ | +| account.setSilenceMode | | ❌ | +| account.unban | Unban | ✅ | +| account.unregisterDevice | | ❌ | + +## Ads, Apps, Asr, Auth, Bugtracker + +The current iteration skips this section of the methods + +## Friends + +| Метод API | Метод библиотеки | Состояние | +|---------------------------|--------------------------|-----------| +| friends.add | AddFriend | ✅ | +| friends.addList | AddFriendsList | ✅ | +| friends.areFriends | AreFriends | ✅ | +| friends.delete | DeleteFriend | ✅ | +| friends.deleteAllRequests | DeleteAllFriendsRequests | ✅ | +| friends.deleteList | DeleteFriendsList | ✅ | +| friends.edit | EditFriends | ✅ | +| friends.editList | EditFriendsList | ✅ | +| friends.get | GetFriends | ✅ | +| friends.getAppUsers | GetAppUsersFriends | ❌ | +| friends.getLists | GetFriendsLists | ✅ | +| friends.getMutual | GetMutualFriends | ✅ | +| friends.getOnline | GetOnlineFriends | ✅ | +| friends.getRecent | GetRecentFriends | ✅ | +| friends.getRequests | GetFriendsRequests | ✅ | +| friends.getSuggestions | GetSuggestionsFriends | ✅ | +| friends.search | SearchFriends | ✅ | + +## Groups + +| Метод API | Метод библиотеки | Состояние | +|------------------------------------|----------------------------------|-----------| +| groups.addAddress | AddGroupAddress | ✅ | +| groups.addCallbackServer | AddGroupCallbackServer | ✅ | +| groups.addLink | AddGroupLink | ✅ | +| groups.approveRequest | ApproveRequestGroup | ✅ | +| groups.ban | BanUser | ✅ | +| groups.create | CreateGroup | ✅ | +| groups.deleteAddress | DeleteGroupAddress | ✅ | +| groups.deleteCallbackServer | DeleteGroupCallbackServer | ✅ | +| groups.deleteLink | DeleteGroupLink | ✅ | +| groups.disableOnline | DeleteGroupCallbackServer | ✅ | +| groups.disableOnline | SetGroupOffline | ✅ | +| groups.edit | EditGroup | ✅ | +| groups.editAddress | EditAddressGroup | ❌ | +| groups.editCallbackServer | EditGroupCallbackServer | ✅ | +| groups.editLink | EditGroupLink | ✅ | +| groups.editManager | EditGroupManager | ✅ | +| groups.enableOnline | SetGroupOnline | ✅ | +| groups.get | GetUserGroups | ✅ | +| groups.getById | GetGroup | ✅ | +| groups.getCallbackConfirmationCode | GetGroupCallbackConfirmationCode | ✅ | +| groups.getCallbackServers | GetGroupCallbackServers | ✅ | +| groups.getCallbackSettings | GetGroupCallbackSettings | ✅ | +| groups.getCatalogInfo | GetGroupCatalogInfo | ✅ | +| groups.getInvitedUsers | GetGroupInvitedUsers | ✅ | +| groups.getInvitedUsers | GetGroupInvitedUsers | ✅ | +| groups.getInvites | GetGroupInvites | ✅ | +| groups.getLongPollServer | GetGroupLongPollServer | ✅ | +| groups.getLongPollSettings | GetGroupLongPollSettings | ✅ | +| groups.getMembers | GetGroupMembers | ✅ | +| groups.getOnlineStatus | GetGroupOnlineStatus | ✅ | +| groups.getRequests | GetGroupRequests | ✅ | +| groups.getSettings | GetGroupSettings | ✅ | +| groups.getTagList | GetGroupTagList | ❌ | +| groups.getTokenPermissions | GetGroupTokenPermissions | ✅ | +| groups.invite | InviteGroup | ✅ | +| groups.isMember | IsGroupMember | ✅ | +| groups.join | JoinGroup | ✅ | +| groups.leave | LeaveGroup | ✅ | +| groups.removeUser | RemoveGroupUser | ✅ | +| groups.reorderLink | ReorderGroupLink | ✅ | +| groups.search | SearchGroup | ✅ | +| groups.setCallbackSettings | SetGroupCallbackSettings | ❌ | +| groups.setLongPollSettings | SetGroupLongPollSettings | ✅ | +| groups.setSettings | SetGroupSettings | ❌ | +| groups.setUserNote | SetGroupUserNote | ❌ | +| groups.tagAdd | TagGroupAdd | ❌ | +| groups.tagBind | TagGroupBind | ❌ | +| groups.tagDelete | TagGroupDelete | ❌ | +| groups.tagUpdate | TagGroupUpdate | ❌ | +| groups.toggleMarket | ToggleGroupMarket | ❌ | +| groups.unban | UnbanUser | ✅ | + +## Likes + +| Метод API | Метод библиотеки | Состояние | +|---------------|------------------|-----------| +| likes.add | AddLike | ✅ | +| likes.delete | DeleteLike | ✅ | +| likes.getList | GetLikes | ✅ | +| likes.isLiked | IsLiked | ✅ | + +## Messages + +| Метод API | Метод библиотеки | Состояние | +|-----------------------------------------------|-------------------------------------|-----------| +| messages.addChatUser | AddChatUser | ✅ | +| messages.allowMessagesFromGroup | AllowMessagesFromGroup | ✅ | +| messages.createChat | CreateChat | ✅ | +| messages.delete | Spam, Spams | ✅ | +| messages.delete | DeleteMessage, DeleteMessages | ✅ | +| messages.deleteChatPhoto | DeleteChatPhoto | ✅ | +| messages.deleteConversation | DeleteChat | ✅ | +| messages.deleteReaction | DeleteReaction | ✅ | +| messages.denyMessagesFromGroup | DenyMessagesFromGroup | ✅ | +| messages.edit | EditMessage | ✅ | +| messages.editChat | EditChatTitle | ✅ | +| messages.getByConversationMessageId | GetChatMessageID, GetChatMessageIDs | 🚮 | +| messages.getById | GetMessage, GetMessages | ✅ | +| messages.getChat | GetChat | 🚮 | +| messages.getChatPreview | GetChatPreview | ❌ | +| messages.getConversationMembers | GetChatMembers | ✅ | +| messages.getConversations | GetMyChats | ✅ | +| messages.getConversationsById | GetChat, GetChats | ✅ | +| messages.getHistory | GetChatHistory | ❌ | +| messages.getHistoryAttachments | GetChatHistoryAttachments | ❌ | +| messages.getImportantMessages | GetChatImportantMessages | ❌ | +| messages.getImportantMessages | GetChatImportantMessages | ❌ | +| messages.getIntentUsers | GetIntentUsers | ✅ | +| messages.getInviteLink | GetChatLink | ✅ | +| messages.getLastActivity | GetLastActivity | ✅ | +| messages.getLongPollHistory | GetLongPollHistory | ❌ | +| messages.getLongPollServer | GetUserLongPollServer | ✅ | +| messages.getMessagesReactions | GetMessagesReactions | ✅ | +| messages.getReactedPeers | GetReactionaryMessages | ✅ | +| messages.getReactionsAssets | GetReactionsAssets | ✅ | +| messages.isMessagesFromGroupAllowed | IsMessagesFromGroupAllowed | ✅ | +| messages.joinChatByInviteLink | JoinChatByInviteLink | ✅ | +| messages.markAsAnsweredConversation | MarkChatAsAnswered | ✅ | +| messages.markAsImportant | MarkMessagesAsImportant | ❌ | +| messages.markAsImportantConversation | MarkChatAsAnswered | ❌ | +| messages.markAsRead | MarkMessagesAsRead | ❌ | +| messages.markReactionsAsRead | MarkMessagesReactionAsRead | ❌ | +| messages.pin | PinMessage | ✅ | +| messages.removeChatUser | KickUser | ✅ | +| messages.restore | RestoreMessage | ✅ | +| messages.search | SearchMessages | ❌ | +| messages.searchConversations | SearchChats | ❌ | +| messages.send | SendMessage | ✅ | +| messages.sendMessageEventAnswer | SendMessageEventAnswer | ✅ | +| messages.sendReaction | SendReaction | ✅ | +| messages.setActivity | SetActivity | ✅ | +| messages.setChatPhoto | SetChatPhoto | ❌ | +| messages.unpin | UnpinMessage | ❌ | +| messages.changeConversationMemberRestrictions | MuteUser | ❌ | + +## Status + +| Метод API | Метод библиотеки | Состояние | +|------------|------------------|-----------| +| status.get | GetStatus | ✅ | +| status.set | SetStatus | ✅ | + +## Storage + +| Метод API | Метод библиотеки | Состояние | +|-----------------|------------------|-----------| +| storage.get | GetStatus | ✅ | +| storage.getKeys | GetStorageKeys | ✅ | +| storage.set | SetStatus | ✅ | + +## Store + +| Метод API | Метод библиотеки | Состояние | +|-------------------|------------------|-----------| +| store.getProducts | GetStickers | ✅ | + +## Users + +| Метод API | Метод библиотеки | Состояние | +|------------------------|-------------------|-----------| +| users.get | GetUsers, GetUser | ✅ | +| users.getFollowers | GetFollowers | ✅ | +| users.getSubscriptions | GetSubscriptions | ✅ | +| users.report | ReportUser | ✅ | +| users.search | SearchUser | ✅ | \ No newline at end of file diff --git a/api/account.go b/api/account.go new file mode 100644 index 0000000..8866bbb --- /dev/null +++ b/api/account.go @@ -0,0 +1,113 @@ +package api + +import ( + "fmt" + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) Ban(ownerID int) (bool, error) { + reply := responses.OperationCode{} + return reply.Code == 1, api.Call("account.ban", fmt.Sprintf("owner_id=%d", ownerID), &reply) +} + +func (api *API) ChangePassword(properties ...any) (string, error) { + query, reply := make(url.Values), responses.ChangePasswordReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.String: schema.NewType(schema.ParameterNames{"old_password", "new_password"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Token, api.Call("account.changePassword", query.Encode(), &reply) +} + +func (api *API) GetActiveOffers(properties ...any) ([]int, error) { + query, reply := make(url.Values), responses.ActiveOffersReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"offset", "count"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Offers, api.Call("account.getActiveOffers", query.Encode(), &reply) +} + +func (api *API) GetAppPermissions(userID int) (int, error) { + reply := responses.AppPermissionsReply{} + return reply.Response, api.Call("account.getAppPermissions", fmt.Sprintf("user_id=%d", userID), &reply) +} + +func (api *API) GetBans(properties ...any) ([]int, []responses.User, error) { + query, reply := make(url.Values), responses.BansReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"offset", "count"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Bans, reply.Response.Users, api.Call("account.getBanned", query.Encode(), &reply) +} + +func (api *API) GetCounters() (responses.Counters, error) { + reply := responses.CountersReply{} + return reply.Response, api.Call("account.getCounters", "", &reply) +} + +func (api *API) GetInfo(properties ...any) (responses.Info, error) { + query, reply := make(url.Values), responses.InfoReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("account.getInfo", query.Encode(), &reply) +} + +func (api *API) GetProfileInfo() (info responses.ProfileInfo, err error) { + reply := responses.ProfileInfoReply{} + return reply.Response, api.Call("account.getProfileInfo", "", &reply) +} + +func (api *API) EditProfileInfo(properties ...any) (int, responses.NameRequest, error) { + query, reply := make(url.Values), responses.EditProfileInfo{} + + schema.NewSchema(schema.TypeDefs{ + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Changed, reply.NameRequest, api.Call("account.saveProfileInfo", query.Encode(), &reply) +} + +func (api *API) EditAccountInfo(properties ...any) (bool, error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("account.setInfo", query.Encode(), &reply) +} + +func (api *API) SetOffline() (bool, error) { + reply := responses.OperationCode{} + return reply.Code == 1, api.Call("account.setOffline", "", &reply) +} + +func (api *API) SetOnline(properties ...any) (bool, error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("account.setOnline", query.Encode(), &reply) +} + +func (api *API) Unban(ownerID int) (bool, error) { + reply := responses.OperationCode{} + return reply.Code == 1, api.Call("account.unban", fmt.Sprintf("owner_id=%d", ownerID), &reply) +} diff --git a/api/api.go b/api/api.go new file mode 100644 index 0000000..cc81701 --- /dev/null +++ b/api/api.go @@ -0,0 +1,186 @@ +package api + +import ( + "context" + "fmt" + "net/http" + "sync" + "time" + + "github.com/aejoy/vkgo/consts" + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo" + "go.uber.org/zap" +) + +type API struct { + *botsgo.Client + ID int `json:"id"` + Token string `json:"token"` + Version string `json:"version"` + IsGroup bool `json:"is_group"` + ContentType string + Limit int + mutex sync.Mutex + time time.Time + rps int +} + +func NewCommunity(communityID int, token string, properties ...any) (*API, error) { + return New(&API{ + ID: communityID, + Token: token, + Limit: consts.CommunityAPILimit, + }, properties) +} + +func NewUser(userID int, token string, properties ...any) (*API, error) { + return New(&API{ + ID: userID, + Token: token, + Limit: consts.CommunityAPILimit, + }, properties) +} + +func New(properties ...any) (*API, error) { + client, err := botsgo.NewClient("https://api.vk.com/method") + if err != nil { + return nil, err + } + + client.Logger, err = zap.NewProduction() + if err != nil { + return nil, err + } + + bot := &API{ + Client: client, + Version: consts.DefaultAPIVersion, + ContentType: "application/msgpack", + Limit: consts.UserAPILimit, + } + + for _, property := range properties { + switch property := property.(type) { + case *API: + botProperties(bot, property) + case int: + bot.ID = property + case string: + bot.Token = property + case float32: + bot.Version = fmt.Sprint(property) + case *zap.Logger: + bot.Client.Logger = property + } + } + + if bot.ID != 0 { + return bot, nil + } + + if group, err := bot.GetGroup(); err != nil { + user, err := bot.GetUser() + if err != nil { + return nil, err + } + + bot.ID = user.ID + } else { + bot.ID = group.ID + bot.IsGroup = true + bot.Limit = consts.CommunityAPILimit + } + + bot.Client.Logger.Info(fmt.Sprintf("Connected to %d", bot.ID)) + + return bot, nil +} + +func botProperties(bot, property *API) { + if property.ID != 0 { + bot.ID = property.ID + } + + if property.Token != "" { + bot.Token = property.Token + } + + if property.Version != "" { + bot.Version = property.Version + } + + if property.ContentType != "" { + bot.ContentType = property.ContentType + } + + if property.Limit != 0 { + bot.Limit = property.Limit + } + + if property.Client != nil { + if property.Client.HTTPClient != nil { + bot.Client.HTTPClient = property.Client.HTTPClient + } + + if property.APIURL != "" { + bot.Client.APIURL = property.APIURL + } + + if property.Client.Logger != nil { + bot.Client.Logger = property.Client.Logger + } + } +} + +func (api *API) Call(method string, query string, response responses.Response) error { + if api.Limit > 0 { + api.mutex.Lock() + + sleepTime := time.Second - time.Since(api.time) + if sleepTime < 0 { + api.time = time.Now() + api.rps = 0 + } else if api.rps == api.Limit { + time.Sleep(sleepTime) + api.time = time.Now() + api.rps = 0 + } + + api.rps++ + api.mutex.Unlock() + } + + // code from VK SDK, thanks <3 + + if api.ContentType == "application/msgpack" { + method += ".msgpack" + } + + req, err := api.Client.NewRequest(context.Background()) + if err != nil { + return err + } + + req.Method(http.MethodGet) + + req.Path(fmt.Sprintf("/method/%s?v=%s&%s", method, api.Version, query)) + req.Response(&response) + + req.SetHeader("Authorization", "Bearer "+api.Token) + + res, err := req.Do() + if err != nil { + return err + } + + if err := res.Body.Close(); err != nil { + return err + } + + if err := response.GetError(); err != nil { + return err + } + + return nil +} diff --git a/api/config.go b/api/config.go new file mode 100644 index 0000000..78f47c5 --- /dev/null +++ b/api/config.go @@ -0,0 +1,11 @@ +package api + +func (api *API) SetMessagePack() string { + api.ContentType = "application/msgpack" + return api.ContentType +} + +func (api *API) SetJSON() string { + api.ContentType = "application/json" + return api.ContentType +} diff --git a/api/documentation.go b/api/documentation.go new file mode 100644 index 0000000..a04adbe --- /dev/null +++ b/api/documentation.go @@ -0,0 +1,10 @@ +package api + +import ( + "github.com/aejoy/vkgo/responses" +) + +func (api *API) GetHealth() (statuses []responses.HealthStatus, err error) { + reply := responses.HealthReply{} + return statuses, api.Call("documentation.getPlatformHealthStatuses", "", &reply) +} diff --git a/api/execute.go b/api/execute.go new file mode 100644 index 0000000..5f36487 --- /dev/null +++ b/api/execute.go @@ -0,0 +1,20 @@ +package api + +import ( + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) Execute(properties ...any) (any, error) { + query, reply := make(url.Values), responses.Execute{} + + schema.NewSchema(schema.TypeDefs{ + schema.Float: schema.NewType(schema.ParameterNames{"func_v"}), + schema.String: schema.NewType(schema.ParameterNames{"code"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Result, api.Call("execute", query.Encode(), &reply) +} diff --git a/api/friends.go b/api/friends.go new file mode 100644 index 0000000..6f34271 --- /dev/null +++ b/api/friends.go @@ -0,0 +1,190 @@ +package api + +import ( + "fmt" + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) AddFriend(properties ...any) (int, error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id", "follow"}), + schema.String: schema.NewType(schema.ParameterNames{"text"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code, api.Call("friends.add", query.Encode(), &reply) +} + +func (api *API) AddFriendsList(properties ...any) (int, error) { + query, reply := make(url.Values), responses.AddFriendsListReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_ids"}), + schema.String: schema.NewType(schema.ParameterNames{"name"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.ListID, api.Call("friends.addList", query.Encode(), &reply) +} + +func (api *API) AreFriends(properties ...any) ([]responses.AreFriend, error) { + query, reply := url.Values{ + "extended": {"1"}, + }, responses.AreFriendsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_ids", "need_sign"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"user_ids"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("friends.areFriends", query.Encode(), &reply) +} + +func (api *API) DeleteFriend(userID int) (responses.DeleteFriend, error) { + reply := responses.DeleteFriendReply{} + return reply.Response, api.Call("friends.delete", fmt.Sprintf("user_id=%d", userID), &reply) +} + +func (api *API) DeleteAllFriendsRequests() (bool, error) { + reply := responses.OperationCode{} + return reply.Code == 1, api.Call("friends.deleteAllRequests", "", &reply) +} + +func (api *API) DeleteFriendsList(listID int) (bool, error) { + reply := responses.OperationCode{} + return reply.Code == 1, api.Call("friends.deleteList", fmt.Sprintf("list_id=%d", listID), &reply) +} + +func (api *API) EditFriends(properties ...any) (bool, error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"list_ids", "user_id"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"list_ids"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("friends.edit", query.Encode(), &reply) +} + +func (api *API) EditFriendsList(properties ...any) (bool, error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"list_id"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"add_user_ids"}), + schema.String: schema.NewType(schema.ParameterNames{"name"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("friends.editList", query.Encode(), &reply) +} + +func (api *API) GetFriends(properties ...any) ([]responses.User, error) { + query, reply := url.Values{ + "fields": {"a,"}, + }, responses.FriendsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Friends, api.Call("friends.get", query.Encode(), &reply) +} + +func (api *API) GetFriendsLists(properties ...any) ([]responses.FriendsListItem, error) { + query, reply := make(url.Values), responses.FriendsListsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"return_system", "user_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Items, api.Call("friends.getLists", query.Encode(), &reply) +} + +func (api *API) GetMutualFriends(properties ...any) ([]responses.MutualFriend, error) { + query, reply := make(url.Values), responses.MutualFriendsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"target_uids", "source_uid", "offset"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"target_uids"}), + schema.String: schema.NewType(schema.ParameterNames{"order"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("friends.getMutual", query.Encode(), &reply) +} + +func (api *API) GetOnlineFriends(properties ...any) ([]int, []int, error) { + query, reply := url.Values{ + "online_mobile": {"1"}, + }, responses.OnlineFriendsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id", "list_id"}), + schema.String: schema.NewType(schema.ParameterNames{"order"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Online, reply.Response.OnlineMobile, api.Call("friends.getOnline", query.Encode(), &reply) +} + +func (api *API) GetRecentFriends(properties ...any) ([]int, error) { + query, reply := make(url.Values), responses.RecentFriendsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"count"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("friends.getRecent", query.Encode(), &reply) +} + +func (api *API) GetFriendsRequests(properties ...any) ([]responses.User, error) { + query, reply := url.Values{ + "extended": {"1"}, + }, responses.FriendsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"out"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Friends, api.Call("friends.getRequests", query.Encode(), &reply) +} + +func (api *API) GetSuggestionsFriends(properties ...any) ([]responses.User, error) { + query, reply := url.Values{ + "extended": {"1"}, + }, responses.FriendsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Integer: schema.NewType(schema.ParameterNames{"offset", "count"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Friends, api.Call("friends.getSuggestions", query.Encode(), &reply) +} + +func (api *API) SearchFriends(properties ...any) ([]responses.User, error) { + query, reply := make(url.Values), responses.FriendsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id", "offset", "count"}), + schema.String: schema.NewType(schema.ParameterNames{"q", "name_case"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Friends, api.Call("friends.search", query.Encode(), &reply) +} diff --git a/api/gifts.go b/api/gifts.go new file mode 100644 index 0000000..32f97ff --- /dev/null +++ b/api/gifts.go @@ -0,0 +1,19 @@ +package api + +import ( + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) GetGifts(properties ...any) (int, []responses.Gift, error) { + query, reply := make(url.Values), responses.GiftsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id", "offset", "count"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Count, reply.Response.Gifts, api.Call("gifts.get", query.Encode(), &reply) +} diff --git a/api/groups.go b/api/groups.go new file mode 100644 index 0000000..0d40752 --- /dev/null +++ b/api/groups.go @@ -0,0 +1,443 @@ +package api + +import ( + "fmt" + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) AddGroupAddress(properties ...any) (addGroupAddress responses.AddGroupAddress, err error) { + query, reply := make(url.Values), responses.AddGroupAddressReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "country_id", "city_id", "metro_id"}), + schema.String: schema.NewType(schema.ParameterNames{"title", "address", "latitude", "longitude", "phone", "metro_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("groups.addAddress", query.Encode(), &reply) +} + +func (api *API) AddGroupCallbackServer(properties ...any) (addGroupAddress responses.AddGroupCallbackServer, err error) { + query, reply := make(url.Values), responses.AddGroupCallbackServerReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id"}), + schema.String: schema.NewType(schema.ParameterNames{"url", "title", "secret_key"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("groups.addCallbackServer", query.Encode(), &reply) +} + +func (api *API) AddGroupLink(properties ...any) (addGroupAddress responses.AddGroupAddress, err error) { + query, reply := make(url.Values), responses.AddGroupAddressReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id"}), + schema.String: schema.NewType(schema.ParameterNames{"link", "text"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("groups.addLink", query.Encode(), &reply) +} + +func (api *API) ApproveRequestGroup(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "user_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.approveRequest", query.Encode(), &reply) +} + +func (api *API) BanUser(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "owner_id", "end_date", "comment_visible"}), + schema.String: schema.NewType(schema.ParameterNames{"comment"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.ban", query.Encode(), &reply) +} + +func (api *API) CreateGroup(properties ...any) (group responses.Group, err error) { + query, reply := make(url.Values), responses.CreateGroup{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"subtype", "public_category", "public_subcategory"}), + schema.String: schema.NewType(schema.ParameterNames{"type", "title", "description"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("groups.create", query.Encode(), &reply) +} + +func (api *API) DeleteGroupAddress(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "address_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.deleteAddress", query.Encode(), &reply) +} + +func (api *API) DeleteGroupCallbackServer(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "server_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.deleteCallbackServer", query.Encode(), &reply) +} + +func (api *API) DeleteGroupLink(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "link_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.deleteLink", query.Encode(), &reply) +} + +func (api *API) SetGroupOffline(groupID int) (ok bool, err error) { + reply := responses.OperationCode{} + return reply.Code == 1, api.Call("groups.disableOnline", fmt.Sprintf("group_id=%d", groupID), &reply) +} + +func (api *API) EditGroup(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "access", "subject"}), + schema.String: schema.NewType(schema.ParameterNames{"title", "description", "screen_name"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.edit", query.Encode(), &reply) +} + +func (api *API) EditGroupCallbackServer(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "server_id"}), + schema.String: schema.NewType(schema.ParameterNames{"url", "title", "secret_key"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.editCallbackServer", query.Encode(), &reply) +} + +func (api *API) EditGroupLink(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "link_id"}), + schema.String: schema.NewType(schema.ParameterNames{"text"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.editLink", query.Encode(), &reply) +} + +func (api *API) EditGroupManager(properties ...any) (status string, err error) { + query, reply := make(url.Values), responses.EditGroupManagerReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "user_id", "is_contact"}), + schema.String: schema.NewType(schema.ParameterNames{"role"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Status, api.Call("groups.editManager", query.Encode(), &reply) +} + +func (api *API) SetGroupOnline(groupID int) (ok bool, err error) { + reply := responses.OperationCode{} + return reply.Code == 1, api.Call("groups.enableOnline", fmt.Sprintf("group_id=%d", groupID), &reply) +} + +func (api *API) GetUserGroups(properties ...any) (ok []responses.Group, err error) { + query, reply := url.Values{ + "extended": {"1"}, + }, responses.UserGroupsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"filter", "fields"}), + }).ConvertToQuery(query, properties...) + + return reply.Response.Groups, api.Call("groups.get", query.Encode(), &reply) +} + +func (api *API) GetGroupAddresses(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "offset", "count"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"address_ids", "latitude", "longitude"}), + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.getAddresses", query.Encode(), &reply) +} + +func (api *API) GetBannedUsers(properties ...any) (count int, bans []responses.BannedUserResponse, err error) { + query, reply := make(url.Values), responses.BannedUsersReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "offset", "count"}), + schema.String: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Count, reply.Response.Bans, api.Call("groups.getBanned", query.Encode(), &reply) +} + +func (api *API) GetGroup(properties ...any) (group responses.Group, err error) { + groups, err := api.GetGroups(properties...) + if len(groups) > 0 { + group = groups[0] + } + + return group, err +} + +func (api *API) GetGroups(properties ...any) (groups []responses.Group, err error) { + query, reply := make(url.Values), responses.GroupsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_ids"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"group_ids"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Groups, api.Call("groups.getById", query.Encode(), &reply) +} + +func (api *API) GetGroupCallbackConfirmationCode(groupID int) (confirmationCode string, err error) { + reply := responses.GroupCallbackConfirmationCodeReply{} + return reply.Response.Code, api.Call("groups.getCallbackConfirmationCode", fmt.Sprintf("group_id=%d", groupID), &reply) +} + +func (api *API) GetGroupCallbackServers(properties ...any) (callbackServer []responses.GroupCallbackServer, err error) { + query, reply := make(url.Values), responses.GroupCallbackServersReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"server_ids"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Items, api.Call("groups.getCallbackServers", query.Encode(), &reply) +} + +func (api *API) GetGroupCallbackSettings(properties ...any) (version string, events responses.SettingsEvents, err error) { + query, reply := make(url.Values), responses.GroupCallbackSettingsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "server_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.APIVersion, reply.Response.Events, api.Call("groups.getCallbackSettings", query.Encode(), &reply) +} + +func (api *API) GetGroupCatalogInfo(properties ...any) (enabled int, categories []responses.GroupCatalogInfoCategory, subcategories []responses.Subcategory, err error) { + query, reply := url.Values{ + "extended": {"1"}, + "subcategories": {"1"}, + }, responses.GroupCatalogInfoReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"subcategories"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Enabled, reply.Response.Categories, reply.Response.Subcategories, api.Call("groups.getCatalogInfo", query.Encode(), &reply) +} + +func (api *API) GetGroupInvitedUsers(properties ...any) (enabled int, categories []responses.GroupCatalogInfoCategory, subcategories []responses.Subcategory, err error) { + query, reply := make(url.Values), responses.GroupCatalogInfoReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "offset", "count"}), + schema.String: schema.NewType(schema.ParameterNames{"name_case"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Enabled, reply.Response.Categories, reply.Response.Subcategories, api.Call("groups.getInvitedUsers", query.Encode(), &reply) +} + +func (api *API) GetUserGroupInvites(properties ...any) (all []responses.Group, users []responses.User, groups []responses.Group, err error) { + query, reply := url.Values{ + "extended": {"1"}, + }, responses.GroupInvitesReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"offset", "count"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Groups, reply.Response.Users, reply.Response.Groups, api.Call("groups.getInvites", query.Encode(), &reply) +} + +func (api *API) GetGroupLongPollServer(groupID int) (server responses.LongPollServer, err error) { + reply := responses.LongPollServerReply{} + return reply.Response, api.Call("groups.getLongPollServer", fmt.Sprintf("group_id=%d", groupID), &reply) +} + +func (api *API) GetGroupLongPollSettings(groupID int) (ok bool, version string, events responses.SettingsEvents, err error) { + reply := responses.LongPollSettingsReply{} + return reply.Response.IsEnabled, reply.Response.APIVersion, reply.Response.Events, api.Call("groups.getLongPollSettings", fmt.Sprintf("group_id=%d", groupID), &reply) +} + +func (api *API) GetGroupMembers(properties ...any) (ok []responses.GroupMember, nextFrom string, err error) { + query, reply := url.Values{"fields": {"a,"}}, responses.GroupMembersReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "offset", "count"}), + schema.String: schema.NewType(schema.ParameterNames{"sort"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields", "filter"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Items, reply.Response.NextFrom, api.Call("groups.getMembers", query.Encode(), &reply) +} + +func (api *API) GetGroupOnlineStatus(groupID int) (status string, err error) { + reply := responses.GroupOnlineStatusReply{} + return reply.Response.Status, api.Call("groups.getOnlineStatus", fmt.Sprintf("group_id=%d", groupID), &reply) +} + +func (api *API) GetGroupRequests(properties ...any) (groups []responses.User, err error) { + query, reply := url.Values{"fields": {"a,"}}, responses.GroupRequestsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Items, api.Call("groups.getRequests", query.Encode(), &reply) +} + +func (api *API) GetGroupSettings(groupID int) (groups responses.GroupSettings, err error) { + reply := responses.GroupSettingsReply{} + return reply.Response, api.Call("groups.getSettings", fmt.Sprintf("group_id=%d", groupID), &reply) +} + +func (api *API) GetGroupTokenPermissions() (mask int, permissions []responses.GroupTokenPermission, err error) { + reply := responses.GroupTokenPermissionsReply{} + return reply.Response.Mask, reply.Response.Permissions, api.Call("groups.getTokenPermissions", "", &reply) +} + +func (api *API) InviteGroup(properties ...any) (code bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "user_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.invite", query.Encode(), &reply) +} + +func (api *API) IsGroupMember(properties ...any) (member, canInvite int, err error) { + query, reply := url.Values{"extended": {"1"}}, responses.IsGroupMemberReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "user_id"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"user_ids"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Member, reply.Response.CanInvite, api.Call("groups.isMember", query.Encode(), &reply) +} + +func (api *API) JoinGroup(properties ...any) (code bool, err error) { + query, reply := url.Values{"extended": {"1"}}, responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id"}), + schema.String: schema.NewType(schema.ParameterNames{"not_sure"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.join", query.Encode(), &reply) +} + +func (api *API) LeaveGroup(groupID int) (code bool, err error) { + reply := responses.OperationCode{} + return reply.Code == 1, api.Call("groups.leave", fmt.Sprintf("group_id=%d", groupID), &reply) +} + +func (api *API) RemoveGroupUser(properties ...any) (code bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "user_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.removeUser", query.Encode(), &reply) +} + +func (api *API) ReorderGroupLink(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "link_id", "after"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.reorderLink", query.Encode(), &reply) +} + +func (api *API) SearchGroup(properties ...any) (groups []responses.Group, err error) { + query, reply := make(url.Values), responses.UserGroupsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"country_id", "city_id", "sort"}), + schema.String: schema.NewType(schema.ParameterNames{"q", "type"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Groups, api.Call("groups.search", query.Encode(), &reply) +} + +func (api *API) SetGroupLongPollSettings(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "enabled"}), + schema.String: schema.NewType(schema.ParameterNames{"api_version"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.setLongPollSettings", query.Encode(), &reply) +} + +func (api *API) UnbanUser(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "owner_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("groups.unban", query.Encode(), &reply) +} diff --git a/api/historyMessages.go b/api/historyMessages.go new file mode 100644 index 0000000..3373eda --- /dev/null +++ b/api/historyMessages.go @@ -0,0 +1,23 @@ +package api + +import ( + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) GetHistoryMessages(properties ...any) (historyMessages responses.HistoryMessages, err error) { + query, reply := url.Values{ + "extended": {"1"}, + }, responses.HistoryMessagesReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "offset", "count"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Boolean: schema.NewType(schema.ParameterNames{"rev"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("messages.getHistory", query.Encode(), &reply) +} diff --git a/api/likes.go b/api/likes.go new file mode 100644 index 0000000..9c99eda --- /dev/null +++ b/api/likes.go @@ -0,0 +1,58 @@ +package api + +import ( + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) AddLike(properties ...any) (likes int, reactions responses.Reactions, err error) { + query, reply := make(url.Values), responses.LikeActionReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"owner_id", "item_id"}), + schema.String: schema.NewType(schema.ParameterNames{"type", "access_key"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Likes, reply.Response.Reactions, api.Call("likes.add", query.Encode(), &reply) +} + +func (api *API) DeleteLike(properties ...any) (likes int, reactions responses.Reactions, err error) { + query, reply := make(url.Values), responses.LikeActionReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"owner_id", "item_id"}), + schema.String: schema.NewType(schema.ParameterNames{"type", "access_key"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Likes, reply.Response.Reactions, api.Call("likes.delete", query.Encode(), &reply) +} + +func (api *API) GetLikes(properties ...any) (likes []responses.User, err error) { + query, reply := url.Values{ + "extended": {"1"}, + }, responses.LikesReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"owner_id", "item_id"}), + schema.String: schema.NewType(schema.ParameterNames{"type", "filter"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Users, api.Call("likes.getList", query.Encode(), &reply) +} + +func (api *API) IsLiked(properties ...any) (liked bool, reactionID int, copied bool, err error) { + query, reply := make(url.Values), responses.IsLikedReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"owner_id", "item_id", "user_id"}), + schema.String: schema.NewType(schema.ParameterNames{"type"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Liked == 1, reply.Response.ReactionID, reply.Response.Copied == 1, api.Call("likes.isLiked", query.Encode(), &reply) +} diff --git a/api/messages.go b/api/messages.go new file mode 100644 index 0000000..0cda0f4 --- /dev/null +++ b/api/messages.go @@ -0,0 +1,466 @@ +package api + +import ( + "fmt" + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/aejoy/vkgo/types" + "github.com/aejoy/vkgo/update" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) AddChatUser(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.ResultOperationCodeReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"chat_id", "user_id", "visible_messages_count"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Result == 1, api.Call("messages.addChatUser", query.Encode(), &reply) +} + +func (api *API) AllowMessagesFromGroup(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id"}), + schema.String: schema.NewType(schema.ParameterNames{"key"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.allowMessagesFromGroup", query.Encode(), &reply) +} + +func (api *API) CreateChat(properties ...any) (chatID int, users []int, err error) { + query, reply := make(url.Values), responses.CreateChatReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"user_ids"}), + schema.String: schema.NewType(schema.ParameterNames{"title"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.ChatID, reply.Response.Users, api.Call("messages.createChat", query.Encode(), &reply) +} + +func (api *API) Spam(properties ...any) (message responses.DeleteMessage, err error) { + messages, err := api.Spams(properties...) + if len(messages) > 0 { + message = messages[0] + } + + return message, err +} + +func (api *API) Spams(properties ...any) (messages []responses.DeleteMessage, err error) { + return api.DeleteMessages(append(properties, types.DeleteMessage{Spam: true})...) +} + +func (api *API) DeleteMessage(properties ...any) (message responses.DeleteMessage, err error) { + messages, err := api.DeleteMessages(properties...) + if len(messages) > 0 { + message = messages[0] + } + + return message, err +} + +func (api *API) DeleteMessages(properties ...any) (messages []responses.DeleteMessage, err error) { + query, reply := make(url.Values), responses.DeleteMessages{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "cmids", "delete_for_all", "spam"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"cmids"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Messages, api.Call("messages.delete", query.Encode(), &reply) +} + +func (api *API) DeleteChatPhoto(properties ...any) (messageID int, chat responses.Chat, err error) { + query, reply := make(url.Values), responses.DeleteChatPhotoReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"chat_id", "group_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.MessageID, reply.Response.Chat, api.Call("messages.deleteChatPhoto", query.Encode(), &reply) +} + +func (api *API) DeleteChat(properties ...any) (lastDeletedID int, err error) { + query, reply := make(url.Values), responses.DeleteChatReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "group_id", "offset", "count"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.LastDeletedID, api.Call("messages.deleteConversation", query.Encode(), &reply) +} + +func (api *API) DeleteReaction(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "cmid"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.deleteReaction", query.Encode(), &reply) +} + +func (api *API) DenyMessagesFromGroup(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.denyMessagesFromGroup", query.Encode(), &reply) +} + +func (api *API) EditMessage(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "conversation_message_id"}), + schema.String: schema.NewType(schema.ParameterNames{"message", "attachment"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"attachment"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.edit", query.Encode(), &reply) +} + +func (api *API) EditChatTitle(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"chat_id"}), + schema.String: schema.NewType(schema.ParameterNames{"title"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.editChat", query.Encode(), &reply) +} + +func (api *API) GetMessage(properties ...any) (message update.Message, users []responses.User, groups []responses.Group, err error) { + messages, err := api.GetMessages(properties...) + if len(messages.Messages) > 0 { + message = messages.Messages[0] + } + + return message, messages.Users, messages.Groups, err +} + +func (api *API) GetMessages(properties ...any) (messages responses.Messages, err error) { + query, reply := make(url.Values), responses.MessagesReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "cmids", "group_id"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"cmids"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + if err = api.Call("messages.getById", query.Encode(), &reply); err != nil { + return + } + + for _, message := range reply.Response.Messages { + if payload, err := update.DecodePayload(message.RawPayload); err == nil { + message.Payload = payload + } + } + + return reply.Response, err +} + +func (api *API) GetChatMembers(properties ...any) (members responses.ChatMembers, err error) { + query, reply := url.Values{ + "extended": {"1"}, + }, responses.ChatMembersReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "offset", "group_id"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("messages.getConversationMembers", query.Encode(), &reply) +} + +func (api *API) GetMyChats(properties ...any) (chats responses.Chats, err error) { + query, reply := url.Values{ + "extended": {"1"}, + }, responses.ChatsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_ids", "group_id"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"peer_ids"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("messages.getConversations", query.Encode(), &reply) +} + +func (api *API) GetChat(properties ...any) (chat responses.Conversation, users []responses.User, groups []responses.Group, err error) { + chats, err := api.GetChats(properties...) + if len(chats.Chats) > 0 { + chat = chats.Chats[0] + } + + return chat, chats.Users, chats.Groups, err +} + +func (api *API) GetChats(properties ...any) (chats responses.Chats, err error) { + query, reply := url.Values{ + "extended": {"1"}, + }, responses.ChatsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_ids", "group_id"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"peer_ids"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Boolean: schema.NewType(schema.ParameterNames{"extended"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("messages.getConversationsById", query.Encode(), &reply) +} + +func (api *API) GetIntentUsers(properties ...any) (chats responses.Chats, err error) { + query, reply := make(url.Values), responses.ChatsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"subscribe_id"}), + schema.String: schema.NewType(schema.ParameterNames{"intent", "fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("messages.getIntentUsers", query.Encode(), &reply) +} + +func (api *API) GetChatLink(properties ...any) (link string, err error) { + query, reply := make(url.Values), responses.ChatLinkReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "reset", "group_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Link, api.Call("messages.getInviteLink", query.Encode(), &reply) +} + +func (api *API) GetLastActivity(properties ...any) (online bool, time int, err error) { + query, reply := make(url.Values), responses.LastActivityReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Online == 1, reply.Response.Time, api.Call("messages.getLastActivity", query.Encode(), &reply) +} + +func (api *API) GetUserLongPollServer(properties ...any) (server responses.LongPollServer, err error) { + query, reply := make(url.Values), responses.LongPollServerReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"lp_version", "need_pts", "group_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("messages.getLongPollServer", query.Encode(), &reply) +} + +func (api *API) GetMessagesReactions(properties ...any) (reactions []responses.MessagesReaction, err error) { + query, reply := make(url.Values), responses.MessagesReactionsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "cmids"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"cmids"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Items, api.Call("messages.getMessagesReactions", query.Encode(), &reply) +} + +func (api *API) GetReactionaryMessages(properties ...any) (counters []responses.ReactionaryMessagesCounters, reactions []responses.ReactionaryMessagesReactions, err error) { + query, reply := make(url.Values), responses.ReactionaryMessagesReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "cmid", "reaction_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Counters, reply.Response.Reactions, api.Call("messages.getReactedPeers", query.Encode(), &reply) +} + +func (api *API) GetReactionsAssets(properties ...any) (version int, reactionIDs []int, assets []responses.ReactionsAsset, err error) { + query, reply := make(url.Values), responses.ReactionsAssetsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"client_version"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Version, reply.Response.ReactionIDs, reply.Response.Assets, api.Call("messages.getReactionsAssets", query.Encode(), &reply) +} + +func (api *API) IsMessagesFromGroupAllowed(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.IsMessagesFromGroupAllowedReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id", "user_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.IsAllowed == 1, api.Call("messages.isMessagesFromGroupAllowed", query.Encode(), &reply) +} + +func (api *API) JoinChatByInviteLink(properties ...any) (chatID int, err error) { + query, reply := make(url.Values), responses.JoinChatByInviteLinkReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.String: schema.NewType(schema.ParameterNames{"link"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.ChatID, api.Call("messages.joinChatByInviteLink", query.Encode(), &reply) +} + +func (api *API) MarkChatAsAnswered(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "answered", "group_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.markAsAnsweredConversation", query.Encode(), &reply) +} + +func (api *API) PinMessage(properties ...any) (message responses.PinMessage, err error) { + query, reply := make(url.Values), responses.PinMessageReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "conversation_message_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("messages.pin", query.Encode(), &reply) +} + +func (api *API) KickUser(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"chat_id", "member_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.removeChatUser", query.Encode(), &reply) +} + +func (api *API) RestoreMessage(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"message_id", "group_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.restore", query.Encode(), &reply) +} + +func (api *API) SendMessage(properties ...any) (message responses.SendMessage, err error) { + sent, err := api.SendMessages(properties...) + if len(sent) > 0 { + message = sent[0] + } + + return message, err +} + +func (api *API) SendMessages(properties ...any) (messages []responses.SendMessage, err error) { + query, reply := url.Values{ + "random_id": {fmt.Sprint(types.NewRandomID())}, + }, responses.SendMessageReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_ids"}), + schema.String: schema.NewType(schema.ParameterNames{"message", "attachment"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"peer_ids"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"attachment"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("messages.send", query.Encode(), &reply) +} + +func (api *API) SendMessageEventAnswer(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.SendEventMessage{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "user_id"}), + schema.String: schema.NewType(schema.ParameterNames{"event_id", "event_data"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.sendMessageEventAnswer", query.Encode(), &reply) +} + +func (api *API) SendReaction(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.SendEventMessage{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "cmid", "reaction_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.sendReaction", query.Encode(), &reply) +} + +func (api *API) SetActivity(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.SendEventMessage{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "group_id"}), + schema.String: schema.NewType(schema.ParameterNames{"type"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.setActivity", query.Encode(), &reply) +} + +func (api *API) UnpinMessage(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "group_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("messages.unpin", query.Encode(), &reply) +} + +// without documentation + +func (api *API) MuteUser(properties ...any) (mute responses.MuteUser, err error) { + query, reply := make(url.Values), responses.MuteUserReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id", "member_ids"}), + schema.Duration: schema.NewType(schema.ParameterNames{"for"}), + schema.String: schema.NewType(schema.ParameterNames{"action"}), + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("messages.changeConversationMemberRestrictions", query.Encode(), &reply) +} diff --git a/api/photos.go b/api/photos.go new file mode 100644 index 0000000..d009cbb --- /dev/null +++ b/api/photos.go @@ -0,0 +1,35 @@ +package api + +import ( + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/aejoy/vkgo/update" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) GetAlbums(properties ...any) ([]responses.Album, error) { + query, reply := make(url.Values), responses.AlbumsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"owner_id"}), + schema.String: schema.NewType(schema.ParameterNames{"action"}), + schema.Duration: schema.NewType(schema.ParameterNames{"for"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Albums, api.Call("photos.getAlbums", query.Encode(), &reply) +} + +func (api *API) GetPhotos(properties ...any) ([]update.Photo, error) { + query, reply := make(url.Values), responses.AlbumPhotosReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"owner_id", "album_id"}), + schema.String: schema.NewType(schema.ParameterNames{"action"}), + schema.Boolean: schema.NewType(schema.ParameterNames{"rev"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Photos, api.Call("photos.get", query.Encode(), &reply) +} diff --git a/api/status.go b/api/status.go new file mode 100644 index 0000000..326b10b --- /dev/null +++ b/api/status.go @@ -0,0 +1,31 @@ +package api + +import ( + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) GetStatus(properties ...any) (text string, err error) { + query, reply := make(url.Values), responses.StatusReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id", "group_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Text, api.Call("status.get", query.Encode(), &reply) +} + +func (api *API) SetStatus(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id"}), + schema.String: schema.NewType(schema.ParameterNames{"text"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("status.set", query.Encode(), &reply) +} diff --git a/api/storage.go b/api/storage.go new file mode 100644 index 0000000..0588e15 --- /dev/null +++ b/api/storage.go @@ -0,0 +1,37 @@ +package api + +import ( + "fmt" + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) GetStorage(properties ...any) (storages responses.Storages, err error) { + query, reply := make(url.Values), responses.StorageReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id"}), + schema.String: schema.NewType(schema.ParameterNames{"key"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"keys"}), + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("storage.get", query.Encode(), &reply) +} + +func (api *API) GetStorageKeys(userID int) (keys []string, err error) { + reply := responses.StorageKeysReply{} + return reply.Response, api.Call("storage.getKeys", fmt.Sprintf("user_id=%d", userID), &reply) +} + +func (api *API) SetStorage(properties ...any) (result any, err error) { + query, reply := make(url.Values), responses.SetStorageReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id"}), + schema.String: schema.NewType(schema.ParameterNames{"key", "value"}), + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("storage.set", query.Encode(), &reply) +} diff --git a/api/store.go b/api/store.go new file mode 100644 index 0000000..b61e911 --- /dev/null +++ b/api/store.go @@ -0,0 +1,23 @@ +package api + +import ( + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) GetStickers(properties ...any) (stickers []responses.Sticker, err error) { + query, reply := url.Values{ + "type": {"stickers"}, + "filters": {"purchased"}, + }, responses.StickersReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"filters"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Stickers, api.Call("store.getProducts", query.Encode(), &reply) +} diff --git a/api/uploadAlbumPhoto.go b/api/uploadAlbumPhoto.go new file mode 100644 index 0000000..5922492 --- /dev/null +++ b/api/uploadAlbumPhoto.go @@ -0,0 +1,64 @@ +package api + +import ( + "net/url" + + "github.com/aejoy/vkgo/types" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) GetUploadAlbumPhotoServer(properties ...any) (server responses.UploadMessagesPhotoServer, err error) { + query, reply := make(url.Values), responses.UploadMessagesPhotoServerReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"album_id", "group_id"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("photos.getUploadServer", query.Encode(), &reply) +} + +func (api *API) SaveUploadAlbumPhoto(properties ...any) (photos []responses.SaveUploadAlbumPhoto, err error) { + query, reply := make(url.Values), responses.SaveUploadAlbumPhotoReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"server", "album_id", "group_id"}), + schema.String: schema.NewType(schema.ParameterNames{"photos_list", "hash", "caption"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("photos.save", query.Encode(), &reply) +} + +func (api *API) UploadAlbumPhotos(albumID int, files []types.UploadFile, properties ...any) (photo []responses.SaveUploadAlbumPhoto, err error) { + args := []any{albumID} + args = append(args, properties...) + + server, err := api.GetUploadAlbumPhotoServer(args...) + if err != nil { + return photo, err + } + + uploaded, err := api.UploadFiles(server.UploadURL, files) + if err != nil { + return photo, err + } + + photoFile := responses.UploadPhotoFile{} + if err = uploaded.JSON(&photoFile); err != nil { + return photo, err + } + + saveArgs := []any{photoFile.Server} + saveArgs = append(saveArgs, args...) + saveArgs = append(saveArgs, photoFile.PhotosList, photoFile.Hash) + + photos, err := api.SaveUploadAlbumPhoto(saveArgs...) + if err != nil { + return photo, err + } + + return photos, err +} diff --git a/api/uploadFiles.go b/api/uploadFiles.go new file mode 100644 index 0000000..bfaa215 --- /dev/null +++ b/api/uploadFiles.go @@ -0,0 +1,58 @@ +package api + +import ( + "bytes" + "context" + "io" + "mime/multipart" + "net/http" + + "github.com/aejoy/vkgo/responses" + "github.com/aejoy/vkgo/types" +) + +func (api *API) UploadFiles(serverURL string, files []types.UploadFile) (uploadedFile responses.UploadedFiles, err error) { + var ( + body = new(bytes.Buffer) + write = multipart.NewWriter(body) + ) + + for _, file := range files { + part, err := write.CreateFormFile(file.FieldName, file.FileName) + if err != nil { + return nil, err + } + + _, err = io.Copy(part, bytes.NewReader(file.Bytes)) + if err != nil { + return nil, err + } + } + + contentType := write.FormDataContentType() + _ = write.Close() + + request, err := http.NewRequestWithContext(context.Background(), "POST", serverURL, body) + if err != nil { + return nil, err + } + + request.Header.Set("Content-Type", contentType) + + res, err := api.Client.HTTPClient.Do(request) + if err != nil { + err := res.Body.Close() + if err != nil { + return nil, err + } + + return nil, err + } + + data, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + return data, nil +} diff --git a/api/uploadMessagesDocument.go b/api/uploadMessagesDocument.go new file mode 100644 index 0000000..f9edf11 --- /dev/null +++ b/api/uploadMessagesDocument.go @@ -0,0 +1,49 @@ +package api + +import ( + "net/url" + + "github.com/aejoy/vkgo/types" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) GetUploadMessagesDocumentServer(properties ...any) (server responses.UploadMessagesDocumentServer, err error) { + query, reply := make(url.Values), responses.UploadMessagesDocumentServerReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"peer_id"}), + schema.String: schema.NewType(schema.ParameterNames{"type"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("docs.getMessagesUploadServer", query.Encode(), &reply) +} + +func (api *API) SaveUploadMessagesDocument(file string) (typ string, document responses.SaveUploadMessageDocument, err error) { + query, reply := url.Values{ + "file": {file}, + }, responses.SaveUploadMessagesDocumentReply{} + + return reply.Response.Type, reply.Response.Document, api.Call("docs.save", query.Encode(), &reply) +} + +func (api *API) UploadMessagesDocument(chatID int, file types.UploadFile) (typ string, document responses.SaveUploadMessageDocument, err error) { + server, err := api.GetUploadMessagesDocumentServer(chatID) + if err != nil { + return "", document, err + } + + uploaded, err := api.UploadFiles(server.UploadURL, []types.UploadFile{file}) + if err != nil { + return "", document, err + } + + documentFile := responses.UploadDocumentFile{} + if err = uploaded.JSON(&documentFile); err != nil { + return "", document, err + } + + return api.SaveUploadMessagesDocument(documentFile.File) +} diff --git a/api/uploadMessagesPhoto.go b/api/uploadMessagesPhoto.go new file mode 100644 index 0000000..b9fd2cb --- /dev/null +++ b/api/uploadMessagesPhoto.go @@ -0,0 +1,55 @@ +package api + +import ( + "fmt" + "net/url" + + "github.com/aejoy/vkgo/types" + + "github.com/aejoy/vkgo/responses" +) + +func (api *API) GetUploadMessagesPhotoServer(chatID int) (server responses.UploadMessagesPhotoServer, err error) { + reply := responses.UploadMessagesPhotoServerReply{} + return reply.Response, api.Call("photos.getMessagesUploadServer", fmt.Sprintf("peer_id=%d", chatID), &reply) +} + +func (api *API) SaveUploadMessagesPhoto(server int, photo, hash string) (photos []responses.SaveUploadMessagesPhoto, err error) { + query, reply := url.Values{ + "server": {fmt.Sprint(server)}, + "photo": {photo}, + "hash": {hash}, + }, responses.SaveUploadMessagesPhotoReply{} + + return reply.Photos, api.Call("photos.saveMessagesPhoto", query.Encode(), &reply) +} + +func (api *API) UploadMessagesPhoto(chatID int, fileName string, fileBytes []byte) (photo responses.SaveUploadMessagesPhoto, err error) { + server, err := api.GetUploadMessagesPhotoServer(chatID) + if err != nil { + return photo, err + } + + uploaded, err := api.UploadFiles(server.UploadURL, []types.UploadFile{ + {FieldName: "photo", FileName: fileName, Bytes: fileBytes}, + }) + if err != nil { + return photo, err + } + + photoFile := responses.UploadPhotoFile{} + if err = uploaded.JSON(&photoFile); err != nil { + return photo, err + } + + photos, err := api.SaveUploadMessagesPhoto(photoFile.Server, photoFile.Photo, photoFile.Hash) + if err != nil { + return photo, err + } + + if len(photos) > 0 { + photo = photos[0] + } + + return photo, err +} diff --git a/api/users.go b/api/users.go new file mode 100644 index 0000000..6414085 --- /dev/null +++ b/api/users.go @@ -0,0 +1,86 @@ +package api + +import ( + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) GetUser(properties ...any) (user responses.User, err error) { + users, err := api.GetUsers(properties...) + if len(users) > 0 { + user = users[0] + } + + return user, err +} + +func (api *API) GetUsers(properties ...any) (user []responses.User, err error) { + query, reply := make(url.Values), responses.UsersReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_ids"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"user_ids"}), + schema.String: schema.NewType(schema.ParameterNames{"user_ids", "name_case"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response, api.Call("users.get", query.Encode(), &reply) +} + +func (api *API) GetFollowers(properties ...any) (friendsCount int, followers []responses.User, err error) { + query, reply := url.Values{ + "fields": {"about"}, + }, responses.FollowersReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id"}), + schema.String: schema.NewType(schema.ParameterNames{"name_case"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.FriendsCount, reply.Response.Items, api.Call("users.getFollowers", query.Encode(), &reply) +} + +func (api *API) GetSubscriptions(properties ...any) (followers []responses.Subscription, err error) { + query, reply := url.Values{ + "extended": {"1"}, + }, responses.SubscriptionsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id"}), + schema.String: schema.NewType(schema.ParameterNames{"name_case"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Response.Items, api.Call("users.getFollowers", query.Encode(), &reply) +} + +func (api *API) ReportUser(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"user_id"}), + schema.String: schema.NewType(schema.ParameterNames{"type", "comment"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("users.report", query.Encode(), &reply) +} + +func (api *API) SearchUser(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.OperationCode{} + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"group_id"}), + schema.String: schema.NewType(schema.ParameterNames{"q"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"fields"}), + schema.Struct: nil, + }).ConvertToQuery(query, properties...) + + return reply.Code == 1, api.Call("users.search", query.Encode(), &reply) +} diff --git a/api/utils.go b/api/utils.go new file mode 100644 index 0000000..45b9b50 --- /dev/null +++ b/api/utils.go @@ -0,0 +1,12 @@ +package api + +import ( + "fmt" + + "github.com/aejoy/vkgo/responses" +) + +func (api *API) ResolveDomain(domain string) (typ string, objectID int, err error) { + reply := responses.ResolveDomainReply{} + return reply.Response.Type, reply.Response.ObjectID, api.Call("utils.resolveScreenName", fmt.Sprintf("screen_name=%s", domain), &reply) +} diff --git a/api/widgets.go b/api/widgets.go new file mode 100644 index 0000000..297f0d1 --- /dev/null +++ b/api/widgets.go @@ -0,0 +1,18 @@ +package api + +import ( + "net/url" + + "github.com/aejoy/vkgo/responses" + "github.com/botscommunity/botsgo/pkg/schema" +) + +func (api *API) UpdateWidgets(properties ...any) (ok bool, err error) { + query, reply := make(url.Values), responses.UpdateWidgetsReply{} + + schema.NewSchema(schema.TypeDefs{ + schema.String: schema.NewType(schema.ParameterNames{"type", "code"}), + }).ConvertToQuery(query, properties...) + + return reply.Response == 1, api.Call("appWidgets.update", query.Encode(), &reply) +} diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 0000000..3d0ee25 --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,3 @@ +# Benchmarks result + +results diff --git a/benchmarks/perf_test.go b/benchmarks/perf_test.go new file mode 100644 index 0000000..e5b71fd --- /dev/null +++ b/benchmarks/perf_test.go @@ -0,0 +1,46 @@ +package benchmarks_test + +import ( + "os" + "strconv" + "testing" + + // "go.uber.org/zap". + + vksdkApi "github.com/SevereCloud/vksdk/api" + vkgoApi "github.com/aejoy/vkgo/api" +) + +func Benchmark_VKGO(b *testing.B) { + communityID, err := strconv.Atoi(os.Getenv("COMMUNITY_ID")) + if err != nil { + b.Fatal(err) + } + + bot, err := vkgoApi.NewCommunity(communityID, os.Getenv("TOKEN")) + if err != nil { + b.Fatal(err) + } + + b.Run("getUser", func(b *testing.B) { + for i := 0; i < b.N; i++ { + if _, err := bot.GetUser(542439242); err != nil { + b.Fatal(err) + } + } + }) +} + +func Benchmark_VKSDK(b *testing.B) { + bot := vksdkApi.NewVK(os.Getenv("TOKEN")) + + b.Run("getUser", func(b *testing.B) { + for i := 0; i < b.N; i++ { + if _, err := bot.UsersGet(vksdkApi.Params{ + "user_ids": 542439242, + }); err != nil { + b.Fatal(err) + } + } + }) +} diff --git a/benchmarks/results.png b/benchmarks/results.png new file mode 100644 index 0000000..e8037bd Binary files /dev/null and b/benchmarks/results.png differ diff --git a/callback/callback.go b/callback/callback.go new file mode 100644 index 0000000..79d2dd9 --- /dev/null +++ b/callback/callback.go @@ -0,0 +1,38 @@ +package callback + +import ( + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/scene" +) + +// Callback 🌍 is a configuration structure of bots, scenes, routers, and "everyone". +type Callback struct { + Bots map[int]*api.API + Scenes *scene.Scenes + Router Router + everyone bool +} + +// New 🌠 returns an instance of *Callback +// Accepts 🤖 *api.API or 🎪 *scene.Scenes arguments. +func New(properties ...any) *Callback { + cb := &Callback{ + Bots: make(map[int]*api.API), + Scenes: scene.NewScene(), + } + + cb.Router = Router{ + Config: cb, + } + + for _, property := range properties { + switch property := property.(type) { + case *api.API: + cb.Bots[property.ID] = property + case *scene.Scenes: + cb.Scenes = property + } + } + + return cb +} diff --git a/callback/config.go b/callback/config.go new file mode 100644 index 0000000..9c0e3eb --- /dev/null +++ b/callback/config.go @@ -0,0 +1,13 @@ +package callback + +import "github.com/aejoy/vkgo/api" + +func (cb *Callback) Add(bot *api.API) bool { + cb.Bots[bot.ID] = bot + return cb.Bots[bot.ID] != nil +} + +func (cb *Callback) Remove(bot *api.API) bool { + delete(cb.Bots, bot.ID) + return cb.Bots[bot.ID] == nil +} diff --git a/callback/router.go b/callback/router.go new file mode 100644 index 0000000..2801c8f --- /dev/null +++ b/callback/router.go @@ -0,0 +1,32 @@ +package callback + +import ( + "encoding/json" + + "github.com/aejoy/vkgo/scene" + "github.com/aejoy/vkgo/update" + fiber "github.com/gofiber/fiber/v2" +) + +type Router struct { + Config *Callback +} + +func (r *Router) Fiber(ctx *fiber.Ctx) error { + updates := update.Update{} + if err := json.Unmarshal(ctx.Body(), &updates); err != nil { + return err + } + + if bot := r.Config.Bots[updates.GroupID]; bot != nil || r.Config.everyone { + if updates.Type == "confirmation" { + return ctx.SendString(ctx.Params("confirmation")) + } + + scene.Use(bot, updates, *r.Config.Scenes) + + return ctx.SendString("ok") + } + + return ctx.SendString("unregistered bot or access is denied to outsiders") +} diff --git a/consts/consts.go b/consts/consts.go new file mode 100644 index 0000000..13ae2f0 --- /dev/null +++ b/consts/consts.go @@ -0,0 +1,21 @@ +package consts + +const ( + DefaultAPIVersion = "5.238" + CommunityAPILimit = 19 + UserAPILimit = 2 + + DefaultLongPollTimeout = 60 + DefaultLongPollMode = 3 + + CommunityBotType = 1 + UserBotType = 2 +) + +const ( + UpdatesStatusOK = iota + UpdatesStatusOutdated + UpdatesStatusExpired + UpdatesStatusLost + UpdatesStatusInvalid +) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f4157d6 --- /dev/null +++ b/go.mod @@ -0,0 +1,40 @@ +module github.com/aejoy/vkgo + +go 1.22.0 + +require ( + github.com/SevereCloud/vksdk v1.10.0 + github.com/botscommunity/botsgo v1.1.1 + github.com/gofiber/fiber/v2 v2.47.0 + github.com/stretchr/testify v1.9.0 + go.uber.org/zap v1.27.0 +) + +require ( + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.16.3 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/philhofer/fwd v1.1.2 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect + github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect + github.com/tinylib/msgp v1.1.8 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.47.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.8.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..112b036 --- /dev/null +++ b/go.sum @@ -0,0 +1,122 @@ +github.com/SevereCloud/vksdk v1.10.0 h1:iKK2hHJSyW2yzd3ask3fxKPxmvAJ+5bqyCs/Sn4IBRQ= +github.com/SevereCloud/vksdk v1.10.0/go.mod h1:BUxU4W2WoFwFU83aopUmXKTjbdgDgEDCTGdOJfdxSB0= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/botscommunity/botsgo v1.1.1 h1:EKd5NFWX2gEHXBhhkINzGDzkQI6Jv5JMt0HUvZXNNgw= +github.com/botscommunity/botsgo v1.1.1/go.mod h1:jLD+h6FqJI4Uu0Lt4G509oYPbtYHzIeS+ngOZR1t4qI= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gofiber/fiber/v2 v2.47.0 h1:EN5lHVCc+Pyqh5OEsk8fzRiifgwpbrP0rulQ4iNf3fs= +github.com/gofiber/fiber/v2 v2.47.0/go.mod h1:mbFMVN1lQuzziTkkakgtKKdjfsXSw9BKR5lmcNksUoU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= +github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= +github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 h1:rmMl4fXJhKMNWl+K+r/fq4FbbKI+Ia2m9hYBLm2h4G4= +github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8= +github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4= +github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk= +github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= +github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= +github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c= +github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/keyboard/buttons.go b/keyboard/buttons.go new file mode 100644 index 0000000..1bcd837 --- /dev/null +++ b/keyboard/buttons.go @@ -0,0 +1,152 @@ +package keyboard + +import ( + "encoding/json" +) + +func TextButton(properties ...any) *Buttons { + return NewText(properties...) +} +func NewText(properties ...any) *Buttons { + keyboard := New().Text(properties...) + if len(keyboard.Buttons) > 0 { + return &keyboard.Buttons[0] + } + + return &Buttons{} +} + +func (buttons *Buttons) TextButton(properties ...any) *Buttons { + return buttons.Text(properties...) +} +func (buttons *Buttons) Text(properties ...any) *Buttons { + keyboard := New().Text(properties...) + if len(keyboard.Buttons) > 0 { + _ = append(*buttons, keyboard.Buttons[0][0]) + return buttons + } + + return buttons +} + +func CallbackButton(properties ...any) *Buttons { + return NewCallback(properties...) +} +func NewCallback(properties ...any) *Buttons { + keyboard := New().Callback(properties...) + if len(keyboard.Buttons) > 0 { + return &keyboard.Buttons[0] + } + + return &Buttons{} +} + +func (buttons *Buttons) CallbackButton(properties ...any) *Buttons { + return buttons.Callback(properties...) +} +func (buttons *Buttons) Callback(properties ...any) *Buttons { + keyboard := New().Callback(properties...) + if len(keyboard.Buttons) > 0 { + _ = append(*buttons, keyboard.Buttons[0][0]) + return buttons + } + + return buttons +} + +func LinkButton(properties ...any) *Buttons { + return NewLink(properties...) +} +func NewLink(properties ...any) *Buttons { + keyboard := New().Link(properties...) + if len(keyboard.Buttons) > 0 { + return &keyboard.Buttons[0] + } + + return &Buttons{} +} + +func (buttons *Buttons) LinkButton(properties ...any) *Buttons { + return buttons.Link(properties...) +} +func (buttons *Buttons) Link(properties ...any) *Buttons { + keyboard := New().Link(properties...) + if len(keyboard.Buttons) > 0 { + _ = append(*buttons, keyboard.Buttons[0][0]) + return buttons + } + + return buttons +} + +func ApplicationButton(properties ...any) *Buttons { + return NewApp(properties...) +} +func AppButton(properties ...any) *Buttons { + return NewApp(properties...) +} + +func NewApplication(properties ...any) *Buttons { + return NewApp(properties...) +} +func NewApp(properties ...any) *Buttons { + keyboard := New().App(properties...) + if len(keyboard.Buttons) > 0 { + return &keyboard.Buttons[0] + } + + return &Buttons{} +} + +func (buttons *Buttons) ApplicationButton(properties ...any) *Buttons { + return buttons.App(properties...) +} +func (buttons *Buttons) AppButton(properties ...any) *Buttons { + return buttons.App(properties...) +} + +func (buttons *Buttons) Application(properties ...any) *Buttons { + return buttons.App(properties...) +} +func (buttons *Buttons) App(properties ...any) *Buttons { + keyboard := New().App(properties...) + if len(keyboard.Buttons) > 0 { + _ = append(*buttons, keyboard.Buttons[0][0]) + return buttons + } + + return buttons +} + +func LocationButton(properties ...any) *Buttons { + return NewLocation(properties...) +} +func NewLocation(properties ...any) *Buttons { + keyboard := New().Location(properties...) + if len(keyboard.Buttons) > 0 { + return &keyboard.Buttons[0] + } + + return &Buttons{} +} + +func (buttons *Buttons) LocationButton(properties ...any) *Buttons { + return buttons.Location(properties...) +} +func (buttons *Buttons) Location(properties ...any) *Buttons { + keyboard := New().Location(properties...) + if len(keyboard.Buttons) > 0 { + _ = append(*buttons, keyboard.Buttons[0][0]) + return buttons + } + + return buttons +} + +func (buttons *Buttons) JSON() string { + if data, err := json.Marshal(buttons); err == nil { + return string(data) + } + + return "" +} diff --git a/keyboard/keyboard.go b/keyboard/keyboard.go new file mode 100644 index 0000000..b9826bd --- /dev/null +++ b/keyboard/keyboard.go @@ -0,0 +1,582 @@ +package keyboard + +import ( + "encoding/json" + "fmt" + "net/url" +) + +type ReplyKeyboard struct { + Disposable bool `json:"one_time"` + Embedded bool `json:"inline"` + Buttons []Buttons `json:"buttons"` +} + +type Buttons []Button +type Button struct { + Action Action `json:"action,omitempty"` + Color string `json:"color,omitempty"` +} + +type Action struct { + Type string `json:"type,omitempty"` + Link string `json:"link,omitempty"` + Label string `json:"label,omitempty"` + + OwnerID int `json:"owner_id,omitempty"` + ApplicationID int `json:"app_id,omitempty"` + Hash string `json:"hash,omitempty"` + + Payload any `json:"payload,omitempty"` +} + +type Label string +type Payload map[string]string +type Color string + +type OwnerID int +type ApplicationID int +type AppID int +type Hash string + +const ( + White = "default" + Default = "default" + Secondary = "default" + + Blue = "primary" + Primary = "primary" + + Green = "positive" + Positive = "positive" + + Red = "negative" + Negative = "negative" +) + +func getColor(color string) (string, bool) { + colors := map[string]string{ + "white": "default", + "blue": "primary", + "green": "positive", + "red": "negative", + } + + vkColor, ok := colors[color] + + return vkColor, ok +} + +type Keyboard struct { + Inline bool + OneTime bool + Buttons any +} + +func New(properties ...any) *ReplyKeyboard { + keyboard := &ReplyKeyboard{ + Buttons: []Buttons{}, + } + + for _, property := range properties { + if property, ok := property.(Keyboard); ok { + keyboard.Disposable = property.OneTime + keyboard.Embedded = property.Inline + + if property.Buttons == nil { + keyboard.Buttons = make([]Buttons, 0) + } + + switch property := property.Buttons.(type) { + case Buttons: + keyboard.Buttons = []Buttons{property} + case []Buttons: + keyboard.Buttons = property + } + } + } + + return keyboard +} + +func (keyboard *ReplyKeyboard) OneTime(property ...bool) *ReplyKeyboard { + return keyboard.SetOneTime(property...) +} + +func (keyboard *ReplyKeyboard) SetOneTime(property ...bool) *ReplyKeyboard { + if len(property) > 0 { + keyboard.Disposable = property[0] + return keyboard + } + + if keyboard.Embedded { + keyboard.Embedded = false + } + + keyboard.Disposable = true + + return keyboard +} + +func (keyboard *ReplyKeyboard) Inline(property ...bool) *ReplyKeyboard { + return keyboard.SetInline(property...) +} + +func (keyboard *ReplyKeyboard) SetInline(property ...bool) *ReplyKeyboard { + if len(property) > 0 { + keyboard.Disposable = property[0] + return keyboard + } + + if keyboard.Disposable { + keyboard.Disposable = false + } + + keyboard.Embedded = true + + return keyboard +} + +func (keyboard *ReplyKeyboard) Add(button Button) *ReplyKeyboard { + var ( + count = len(keyboard.Buttons) + color, ok = getColor(button.Color) + ) + + if ok { + button.Color = color + } + + if count == 0 { + keyboard.Row() + keyboard.Buttons[0] = append(keyboard.Buttons[0], button) + } else { + keyboard.Buttons[count-1] = append(keyboard.Buttons[count-1], button) + } + + return keyboard +} + +func (keyboard *ReplyKeyboard) Row() *ReplyKeyboard { + keyboard.Buttons = append(keyboard.Buttons, make(Buttons, 0)) + return keyboard +} + +type Text struct { + Text string + Label string + Payload any + Color any +} + +type Callback Text + +func (keyboard *ReplyKeyboard) Text(properties ...any) *ReplyKeyboard { + title, payload, color := parsePrimitiveButtonProperties(properties...) + + keyboard.Add(Button{ + Action: Action{Type: "text", Label: title, Payload: payload}, + Color: color, + }) + + return keyboard +} + +func (keyboard *ReplyKeyboard) Callback(properties ...any) *ReplyKeyboard { + title, payload, color := parsePrimitiveButtonProperties(properties...) + + keyboard.Add(Button{ + Action: Action{Type: "callback", Label: title, Payload: payload}, + Color: color, + }) + + return keyboard +} + +type Link struct { + Label string + Link string + Payload string +} + +func (keyboard *ReplyKeyboard) Link(properties ...any) *ReplyKeyboard { + var ( + label string + link string + payload string + ) + + for _, property := range properties { + switch property := property.(type) { + case Link: + if property.Label != "" { + label = property.Label + } + + if property.Link != "" { + link = property.Link + } + + if property.Payload != "" { + payload = property.Payload + } + case string: + if len(property) > 0 { + switch { + case label == "": + label = property + case link == "": + link = property + case (payload == "" && property[0] == '{') || (payload == "" && property != ""): + payload = property + } + } + } + } + + keyboard.Add(Button{ + Action: Action{Type: "open_link", Label: label, Link: link, Payload: payload}, + }) + + return keyboard +} + +type Application struct { + Label string + OwnerID int + ApplicationID int + AppID int + Payload string + Hash string +} + +func (keyboard *ReplyKeyboard) Application(properties ...any) *ReplyKeyboard { + return keyboard.App(properties...) +} + +type applicationProperties struct { + label string + ownerID int + appID int + payload string + hash string +} + +func (keyboard *ReplyKeyboard) App(properties ...any) *ReplyKeyboard { + application := new(applicationProperties) + + for _, property := range properties { + switch property := property.(type) { + case Application: + setApplicationStructProperty(application, property) + case int: + if application.ownerID == 0 { + application.ownerID = property + } else { + application.appID = property + } + case string: + switch { + case application.label == "": + application.label = property + case (application.payload == "" && property[0] == '{') || (application.payload == "" && property != ""): + application.payload = property + case application.hash == "": + application.hash = property + } + } + } + + keyboard.Add(Button{ + Action: Action{ + Type: "open_app", + Label: application.label, + OwnerID: application.ownerID, + ApplicationID: application.appID, + Payload: application.payload, + Hash: application.hash, + }, + }) + + return keyboard +} + +func setApplicationStructProperty(application *applicationProperties, property Application) { + if property.Label != "" { + application.label = property.Label + } + + if property.OwnerID != 0 { + application.ownerID = property.OwnerID + } + + if property.ApplicationID != 0 { + application.appID = property.ApplicationID + } else if property.AppID != 0 { + application.appID = property.ApplicationID + } + + if property.Payload != "" { + application.payload = property.Payload + } + + if property.Hash != "" { + application.hash = property.Hash + } +} + +type VKPay struct { + Payload string + Hash VKPayHash +} +type VKPayHash struct { + GroupID int + UserID int + Action string + Amount int + Description string + Data map[string]any +} + +func (keyboard *ReplyKeyboard) Pay(properties ...any) *ReplyKeyboard { + return keyboard.VKPay(properties...) +} + +func (keyboard *ReplyKeyboard) VKPay(properties ...any) *ReplyKeyboard { + var ( + payload string + hash string + ) + + for _, property := range properties { + switch property := property.(type) { + case VKPay: + if property.Payload != "" { + payload = property.Payload + } + + if property.Hash.Action != "" { + data, _ := json.Marshal(property.Hash) + hash = string(data) + } + case VKPayHash: + switch property.Action { + case "pay-to-group": + payToGroup(property) + case "pay-to-user": + payToUser(property) + case "transfer-to-group": + transferToGroup(property) + case "transfer-to-user": + transferToUser(property) + default: + action := property.Action + if action == "" && action[0] == '{' { + payload = action + } else if hash == "" { + hash = action + } + } + } + } + + keyboard.Add(Button{ + Action: Action{Type: "vkpay", Payload: payload, Hash: hash}, + }) + + return keyboard +} + +func payToGroup(property VKPayHash) string { + hash := "action=pay-to-group" + + if property.GroupID != 0 { + hash += fmt.Sprintf("&group_id=%d", property.GroupID) + } + + if property.Amount != 0 { + hash += fmt.Sprintf("&amount=%d", property.Amount) + } + + if property.Description != "" { + hash += fmt.Sprintf("&description=%s", url.QueryEscape(property.Description)) + } + + if len(property.Data) != 0 { + data, _ := json.Marshal(property.Data) + hash += fmt.Sprintf("&data=%s", url.QueryEscape(string(data))) + } + + return hash +} + +func payToUser(property VKPayHash) string { + hash := "action=pay-to-user" + + if property.Amount != 0 { + hash += fmt.Sprintf("&amount=%d", property.Amount) + } + + if property.Description != "" { + hash += fmt.Sprintf("&description=%s", url.QueryEscape(property.Description)) + } + + if property.UserID != 0 { + hash += fmt.Sprintf("&user_id=%d", property.UserID) + } + + return hash +} + +func transferToGroup(property VKPayHash) string { + hash := "action=transfer-to-group" + + if property.GroupID != 0 { + hash += fmt.Sprintf("&group_id=%d", property.GroupID) + } + + if property.Description != "" { + hash += fmt.Sprintf("&description=%s", url.QueryEscape(property.Description)) + } + + return hash +} + +func transferToUser(property VKPayHash) string { + hash := "action=transfer-to-user" + + if property.UserID != 0 { + hash += fmt.Sprintf("&user_id=%d", property.GroupID) + } + + if property.Description != "" { + hash += fmt.Sprintf("&description=%s", url.QueryEscape(property.Description)) + } + + return hash +} + +type Location struct { + Payload string +} + +func (keyboard *ReplyKeyboard) Location(properties ...any) *ReplyKeyboard { + var payload string + + for _, property := range properties { + switch property := property.(type) { + case Location: + if property.Payload != "" { + payload = property.Payload + } + case string: + payload = property + } + } + + keyboard.Add(Button{ + Action: Action{Type: "location", Payload: payload}, + }) + + return keyboard +} + +// JSON 🍷🧣🍁 turns an object into a JSON format string. +func (keyboard *ReplyKeyboard) JSON() string { + if data, err := json.Marshal(keyboard); err == nil { + return string(data) + } + + return "" +} + +func parsePrimitiveButtonProperty(property any, title, payload, color *string) { + switch property := property.(type) { + case Label: + *title = string(property) + case Payload: + value, _ := json.Marshal(property) + *payload = string(value) + case Color: + *color = string(property) + case Text: + if property.Text != "" { + *title = property.Text + } else if property.Label != "" { + *title = property.Label + } + + if property.Payload != nil { + *payload = payloadToString(property.Payload) + } + + if property.Color != nil { + *color = colorToString(property.Color) + } + case Callback: + if property.Text != "" { + *title = property.Text + } else if property.Label != "" { + *title = property.Label + } + + if property.Payload != nil { + *payload = payloadToString(property.Payload) + } + + if property.Color != nil { + *color = colorToString(property.Color) + } + case string: + if *title == "" { + *title = property + } else if len(property) > 0 { + if (*payload == "" && property[0] == '{') || (*payload == "" && *color != "") { + *payload = property + } else { + *color = property + } + } + } +} + +func checkPayload(payload string) string { + if payload == "" { + payload = "{}" + } + + return payload +} + +func parsePrimitiveButtonProperties(properties ...any) (title, payload, color string) { + for _, property := range properties { + parsePrimitiveButtonProperty(property, &title, &payload, &color) + } + + payload = checkPayload(payload) + + return title, payload, color +} + +func payloadToString(property any) (payload string) { + switch property := property.(type) { + case string: + payload = property + case Payload: + value, _ := json.Marshal(property) + payload = string(value) + } + + return payload +} + +func colorToString(property any) (color string) { + switch property := property.(type) { + case string: + color = property + case Color: + color = string(property) + } + + return color +} diff --git a/longpoll/config.go b/longpoll/config.go new file mode 100644 index 0000000..2748036 --- /dev/null +++ b/longpoll/config.go @@ -0,0 +1,15 @@ +package longpoll + +import ( + "github.com/aejoy/vkgo/scene" +) + +func (lp *LongPoll) SetTimeout(time int) *LongPoll { + lp.Timeout = time + return lp +} + +func (lp *LongPoll) SetScenes(scenes *scene.Scenes) *LongPoll { + lp.Scenes = scenes + return lp +} diff --git a/longpoll/group.go b/longpoll/group.go new file mode 100644 index 0000000..059bc06 --- /dev/null +++ b/longpoll/group.go @@ -0,0 +1,68 @@ +package longpoll + +import ( + "encoding/json" + "fmt" + + "github.com/aejoy/vkgo/consts" + "github.com/aejoy/vkgo/scene" + "github.com/aejoy/vkgo/update" +) + +func (lp *LongPoll) RunGroupLongPoll() { + updatesCh := make(chan update.Update) + go func() { + lp.GetGroupLongPollUpdates(lp.Session.Server, updatesCh) + }() + + for { + upd := <-updatesCh + go func() { + scene.Use(lp.Bot, upd, *lp.Scenes) + }() + } +} + +func (lp *LongPoll) GetGroupLongPollUpdates(server string, dest chan update.Update) { + for { + body, err := lp.getByteUpdates(server) + if err != nil { + return + } + + updates := update.Updates{} + if err := json.Unmarshal(body, &updates); err != nil { + if lp.Bot.Logger != nil { + lp.Bot.Logger.Error(fmt.Sprintf("GroupLongPoll JSON unmarshal error is %s", err.Error())) + } + + return + } + + if lp.Bot.Logger != nil { + lp.Bot.Logger.Info(fmt.Sprintf("GroupLongPoll response is %s", string(body))) + } + + switch updates.Failed { + case consts.UpdatesStatusOK: + lp.Session.TS = updates.TS + + for _, upd := range updates.Updates { + dest <- upd + } + case consts.UpdatesStatusOutdated: + lp.Session.TS = updates.TS + case consts.UpdatesStatusExpired: + if server, err := lp.Bot.GetGroupLongPollServer(lp.Bot.ID); err == nil { + lp.Session.Key = server.Key + } + case consts.UpdatesStatusLost: + if server, err := lp.Bot.GetGroupLongPollServer(lp.Bot.ID); err == nil { + lp.Session.Key = server.Key + lp.Session.TS = server.TS + } + case consts.UpdatesStatusInvalid: + lp.Session.Version = updates.MinVersion + } + } +} diff --git a/longpoll/longpoll.go b/longpoll/longpoll.go new file mode 100644 index 0000000..0c53add --- /dev/null +++ b/longpoll/longpoll.go @@ -0,0 +1,72 @@ +package longpoll + +import ( + "errors" + + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/consts" + "github.com/aejoy/vkgo/responses" + "github.com/aejoy/vkgo/scene" +) + +var ( + ErrNotFound = errors.New("bot not found") + ErrSessionClosed = errors.New("session closed") +) + +// LongPoll - basic configuration structure +// Bot - pointer to the bot parameters +// Session - pointer to the session, received from the Create function +// Scenes - pointer to the list of scenes to process the types of events +// Timeout - time of waiting for the next request. +type LongPoll struct { + Bot *api.API + Session *responses.LongPollServer + Scenes *scene.Scenes + Timeout int + Mode int + BotType int // 1 - community, 2 - user +} + +func New(properties ...any) (*LongPoll, error) { + lp := &LongPoll{ + Session: new(responses.LongPollServer), + Scenes: scene.NewScene(), + Timeout: consts.DefaultLongPollTimeout, + Mode: consts.DefaultLongPollMode, + } + + for _, property := range properties { + switch property := property.(type) { + case *api.API: + lp.Bot = property + case *scene.Scenes: + lp.Scenes = property + } + } + + if lp.Bot.ID == 0 { + return nil, ErrNotFound + } + + switch lp.Bot.IsGroup { + case true: + server, err := lp.Bot.GetGroupLongPollServer(lp.Bot.ID) + if err != nil { + return lp, err + } + + lp.Session = &server + lp.BotType = consts.CommunityBotType + default: + server, err := lp.Bot.GetUserLongPollServer() + if err != nil { + return lp, err + } + + lp.Session = &server + lp.BotType = consts.UserBotType + } + + return lp, nil +} diff --git a/longpoll/start.go b/longpoll/start.go new file mode 100644 index 0000000..d60b889 --- /dev/null +++ b/longpoll/start.go @@ -0,0 +1,90 @@ +package longpoll + +import ( + "context" + "fmt" + "io" + "net/http" + + "github.com/aejoy/vkgo/consts" +) + +func Start(properties ...any) error { + lp, err := New(properties...) + if err != nil { + return err + } + + return lp.Start() +} + +func (lp *LongPoll) Start() error { + if lp.Bot == nil { + return ErrSessionClosed + } + + if lp.Session.Server == "" { + return ErrSessionClosed + } + + switch lp.BotType { + case consts.CommunityBotType: + lp.RunGroupLongPoll() + case consts.UserBotType: + lp.RunUserLongPoll() + default: + return nil + } + + return nil +} + +func (lp *LongPoll) getByteUpdates(server string) ([]byte, error) { + link := fmt.Sprintf("%s?act=a_check&key=%s&ts=%+v&wait=%d&mode=%d&version=%d", server, lp.Session.Key, defineSessionTS(lp.Session.TS), lp.Timeout, lp.Mode, lp.Session.Version) + + request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, link, nil) + if err != nil { + if lp.Bot.Logger != nil { + lp.Bot.Logger.Error(fmt.Sprintf("UserLongPoll NewRequest error is %s", err.Error())) + } + + return nil, err + } + + response, err := lp.Bot.HTTPClient.Do(request) + if err != nil { + if lp.Bot.Logger != nil { + lp.Bot.Logger.Error(fmt.Sprintf("UserLongPoll Do error is %s", err.Error())) + } + + return nil, err + } + + body, err := io.ReadAll(response.Body) + if err != nil { + if err := response.Body.Close(); err != nil { + if lp.Bot.Logger != nil { + lp.Bot.Logger.Error(fmt.Sprintf("UserLongPoll BodyClose error is %s", err.Error())) + } + } + + if lp.Bot.Logger != nil { + lp.Bot.Logger.Error(fmt.Sprintf("UserLongPoll ReadAll error is %s", err.Error())) + } + + return nil, err + } + + return body, nil +} + +func defineSessionTS(sessionTS any) string { + switch offset := sessionTS.(type) { + case uint32, uint64: + return fmt.Sprintf("%d", offset) + case float32, float64: + return fmt.Sprintf("%f", offset) + default: + return fmt.Sprint(offset) + } +} diff --git a/longpoll/user.go b/longpoll/user.go new file mode 100644 index 0000000..d655a68 --- /dev/null +++ b/longpoll/user.go @@ -0,0 +1,73 @@ +package longpoll + +import ( + "encoding/json" + "fmt" + + "github.com/aejoy/vkgo/consts" + states "github.com/aejoy/vkgo/longpoll/user" +) + +func (lp *LongPoll) RunUserLongPoll() { + messagesCh := make(chan []any) + go func() { + lp.GetUserLongPollUpdates("https://"+lp.Session.Server, messagesCh) + }() + + for { + message := <-messagesCh + go func() { + if len(message) != 0 { + if typ, ok := message[0].(float64); ok { + if event := states.GetUpdate(typ); event != nil { + event(lp.Bot, message, *lp.Scenes) + } + } + } + }() + } +} + +func (lp *LongPoll) GetUserLongPollUpdates(server string, dest chan []any) { + for { + body, err := lp.getByteUpdates(server) + if err != nil { + return + } + + messages := states.Messages{} + if err := json.Unmarshal(body, &messages); err != nil { + if lp.Bot.Logger != nil { + lp.Bot.Logger.Error(fmt.Sprintf("MessagesLongPoll JSON unmarshal error is %s", err.Error())) + } + + return + } + + if lp.Bot.Logger != nil { + lp.Bot.Logger.Info(fmt.Sprintf("MessagesLongPoll response is %s", string(body))) + } + + switch messages.Failed { + case consts.UpdatesStatusOK: + lp.Session.TS = messages.TS + + for _, message := range messages.Updates { + dest <- message + } + case consts.UpdatesStatusOutdated: + lp.Session.TS = messages.TS + case consts.UpdatesStatusExpired: + if server, err := lp.Bot.GetUserLongPollServer(); err != nil { + lp.Session.Key = server.Key + } + case consts.UpdatesStatusLost: + if server, err := lp.Bot.GetUserLongPollServer(lp.Bot.ID); err == nil { + lp.Session.Key = server.Key + lp.Session.TS = server.TS + } + case consts.UpdatesStatusInvalid: + lp.Session.Version = messages.MinVersion + } + } +} diff --git a/longpoll/user/events.go b/longpoll/user/events.go new file mode 100644 index 0000000..f10db81 --- /dev/null +++ b/longpoll/user/events.go @@ -0,0 +1,16 @@ +package user + +import ( + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/scene" +) + +type Update func(_ *api.API, _ []any, _ scene.Scenes) string + +func GetUpdate(code float64) Update { + updates := map[float64]Update{ + 4: message, + } + + return updates[code] +} diff --git a/longpoll/user/message.go b/longpoll/user/message.go new file mode 100644 index 0000000..1b6cf3e --- /dev/null +++ b/longpoll/user/message.go @@ -0,0 +1,27 @@ +package user + +import ( + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/scene" + "github.com/aejoy/vkgo/types" +) + +func message(bot *api.API, messages []any, scenes scene.Scenes) string { + if len(messages) >= 1 && scenes.MessageFunc != nil { + if messageID, ok := messages[1].(float64); ok { + message, _, _, err := bot.GetMessage(types.Message{ + MessageIDs: []int{int(messageID)}, + }) + if err != nil { + bot.Logger.Error(err.Error()) + return "" + } + + scenes.MessageFunc(bot, message) + } + + return "message_new" + } + + return "" +} diff --git a/longpoll/user/types.go b/longpoll/user/types.go new file mode 100644 index 0000000..3768469 --- /dev/null +++ b/longpoll/user/types.go @@ -0,0 +1,9 @@ +package user + +type Messages struct { + TS any `json:"ts,omitempty"` + Updates [][]any `json:"updates,omitempty"` + Failed int `json:"failed,omitempty"` + MaxVersion int `json:"max_version"` + MinVersion int `json:"min_version"` +} diff --git a/multibot/multibot.go b/multibot/multibot.go new file mode 100644 index 0000000..8cc72f1 --- /dev/null +++ b/multibot/multibot.go @@ -0,0 +1,65 @@ +package multibot + +import ( + "fmt" + + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/longpoll" + "github.com/aejoy/vkgo/scene" +) + +type MultiBot struct { + Bots []*api.API + Scenes *scene.Scenes +} + +func New(properties ...any) *MultiBot { + mb := new(MultiBot) + + for _, property := range properties { + switch property := property.(type) { + case *api.API: + mb.Bots = append(mb.Bots, property) + case []*api.API: + mb.Bots = append(mb.Bots, property...) + case *scene.Scenes: + mb.Scenes = property + } + } + + if mb.Bots == nil { + mb.Bots = make([]*api.API, 0) + } + + return mb +} + +func (mb *MultiBot) Start() []error { + var ( + errors = make([]error, 0, len(mb.Bots)) + errorsCh = make(chan error) + ) + + for _, bot := range mb.Bots { + go listenBot(bot, mb.Scenes, errorsCh) + } + + for err := range errorsCh { + errors = append(errors, err) + } + + return errors +} + +func listenBot(bot *api.API, scenes *scene.Scenes, errors chan error) { + if bot.Logger != nil { + bot.Logger.Info(fmt.Sprintf("MultiBot LongPoll %d running", bot.ID)) + } + + if err := longpoll.Start(bot, scenes); err != nil { + bot.Logger.Error(fmt.Sprintf("MultiBot LongPoll %d error is %s", bot.ID, err)) + errors <- err + } else { + errors <- nil + } +} diff --git a/preview.png b/preview.png new file mode 100644 index 0000000..f9986d7 Binary files /dev/null and b/preview.png differ diff --git a/responses/account.go b/responses/account.go new file mode 100644 index 0000000..67bc702 --- /dev/null +++ b/responses/account.go @@ -0,0 +1,181 @@ +package responses + +// ChangePassword + +type ChangePasswordReply struct { + ErrorInterface + Response ChangePassword `json:"response,omitempty"` +} + +type ChangePassword struct { + Token string `json:"token,omitempty"` +} + +// GetActiveOffers + +type ActiveOffersReply struct { + ErrorInterface + Response ActiveOffers `json:"response,omitempty"` +} + +type ActiveOffers struct { + Offers []int `json:"items,omitempty"` +} + +// GetAppPermissions + +type AppPermissionsReply struct { + ErrorInterface + Response int `json:"response,omitempty"` +} + +// GetBans + +type BansReply struct { + ErrorInterface + Response Bans `json:"response"` +} + +type Bans struct { + Bans []int `json:"items,omitempty"` + Users []User `json:"profiles,omitempty"` +} + +// GetCounters + +type CountersReply struct { + ErrorInterface + Response Counters `json:"response,omitempty"` +} + +type Counters struct { + Photos int `json:"photos,omitempty"` + Albums int `json:"albums,omitempty"` + Audios int `json:"audios,omitempty"` + Videos int `json:"videos,omitempty"` + Topics int `json:"topics,omitempty"` + Docs int `json:"docs,omitempty"` + + AppRequests int `json:"app_requests,omitempty"` + Faves int `json:"faves,omitempty"` + DiscoverBadge int `json:"menu_discover_badge,omitempty"` + ClipsBadge int `json:"menu_clips_badge,omitempty"` + SuperAppFriendsBadge int `json:"menu_superapp_friends_badge,omitempty"` + NewClipsBadge int `json:"menu_new_clips_badge,omitempty"` + Messages int `json:"messages,omitempty"` + SDK int `json:"sdk,omitempty"` + Calls int `json:"calls,omitempty"` + MessagesFolders []MessagesFolder `json:"messages_folders,omitempty"` + + // without documentation + Addresses int `json:"addresses,omitempty"` + VideoPlaylists int `json:"video_playlists,omitempty"` + Narratives int `json:"narratives,omitempty"` + Clips int `json:"clips,omitempty"` + ClipsFollowers int `json:"clips_followers,omitempty"` + ClassifiedYoula int `json:"classified_youla,omitempty"` +} + +type MessagesFolder struct { + ID int `json:"folder_id,omitempty"` + Count int `json:"total_count,omitempty"` + UnMuted int `json:"unmuted_count,omitempty"` +} + +// GetInfo + +type InfoReply struct { + ErrorInterface + Response Info `json:"response,omitempty"` +} + +type Info struct { + Country string `json:"country,omitempty"` + Secure int `json:"https_required,omitempty"` + TwoFactor int `json:"2fa_required,omitempty"` + OwnerPosts int `json:"own_posts_default,omitempty"` + NoWallReplies int `json:"no_wall_replies,omitempty"` + Intro int `json:"intro,omitempty"` + Language int `json:"lang,omitempty"` + + // without documentation + CommunityComments bool `json:"community_comments,omitempty"` + LinkRedirects map[string]string `json:"link_redirects,omitempty"` + VKPayEndpoint string `json:"vk_pay_endpoint_v2,omitempty"` + Translation []string `json:"messages_translation_language_pairs,omitempty"` + ObsceneFilter bool `json:"obscene_text_filter,omitempty"` +} + +// GetProfileInfo + +type ProfileInfoReply struct { + ErrorInterface + Response ProfileInfo `json:"response,omitempty"` +} + +type ProfileInfo struct { + Name string `json:"first_name,omitempty"` + Surame string `json:"last_name,omitempty"` + MaidenName string `json:"maiden_name,omitempty"` + Domain string `json:"screen_name,omitempty"` + Sex int `json:"sex,omitempty"` + Relation int `json:"relation,omitempty"` // 📡👽 + RelationPartner User `json:"relation_partner,omitempty"` + RelationPending int `json:"relation_pending,omitempty"` + RelationRequests []User `json:"relation_requests,omitempty"` + Birthdate string `json:"bdate,omitempty"` + BirthdateVisibility int `json:"bdate_visibility,omitempty"` + HomeTown string `json:"home_town,omitempty"` + Country Country `json:"country,omitempty"` + City City `json:"city,omitempty"` + NameRequest NameRequest `json:"name_request,omitempty"` + Status string `json:"status"` + Phone string `json:"phone"` + + // without documentation + ID int `json:"id,omitempty"` + Photo200 string `json:"photo_200"` + IsServiceAccount bool `json:"is_service_account"` + IsEsiaVerified bool `json:"is_esia_verified"` + IsEsiaLinked bool `json:"is_esia_linked"` + IsTinkoffLinked bool `json:"is_tinkoff_linked"` + IsTinkoffVerified bool `json:"is_tinkoff_verified"` + IsVerified bool `json:"is_verified"` + IsSberVerified bool `json:"is_sber_verified"` + OauthLinked []string `json:"oauth_linked"` + OauthVerification []any `json:"oauth_verification"` + AccountVerificationProfile AccountVerificationProfile `json:"account_verification_profile"` + VerificationStatus string `json:"verification_status"` + PromoVerifications []any `json:"promo_verifications"` +} + +type AccountVerificationProfile struct { + Name string `json:"first_name,omitempty"` + Surname string `json:"last_name,omitempty"` + MiddleName string `json:"middle_name,omitempty"` + Gender int `json:"sex,omitempty"` + Birthdate string `json:"birthdate,omitempty"` +} + +type PushSettings struct { + Sound int `json:"sound,omitempty"` + NoSound any `json:"no_sound,omitempty"` + UntilDisabled int `json:"disabled_until,omitempty"` + ForeverDisabled any `json:"disabled_forever,omitempty"` + // needs improvement +} + +// EditProfileInfo + +type EditProfileInfo struct { + ErrorInterface + Changed int `json:"changed,omitempty"` + NameRequest NameRequest `json:"name_request,omitempty"` +} + +type NameRequest struct { + ID int `json:"id,omitempty"` + Status string `json:"status,omitempty"` + Name string `json:"first_name,omitempty"` + Surname string `json:"last_name,omitempty"` +} diff --git a/responses/albums.go b/responses/albums.go new file mode 100644 index 0000000..d40283d --- /dev/null +++ b/responses/albums.go @@ -0,0 +1,31 @@ +package responses + +import "github.com/aejoy/vkgo/update" + +type AlbumsReply struct { + ErrorInterface + Response Albums `json:"response"` +} + +type Albums struct { + Albums []Album `json:"items"` +} + +type Album struct { + ID int `json:"id"` + CoverID int `json:"thumb_id"` + CoverURL int `json:"thumb_src"` + OwnerID int `json:"owner_id"` + Title string `json:"title"` + Description string `json:"description"` + CreatedAt int `json:"created,omitempty"` + UpdatedAt int `json:"updated,omitempty"` + Count int `json:"size"` + Sizes []update.PhotoSize `json:"sizes"` + CanUpload int `json:"can_upload"` + CanDelete bool `json:"can_delete,omitempty"` + FeedDisabled int `json:"feed_disabled,omitempty"` + FeedHasPinned int `json:"feed_has_pinned,omitempty"` + CanIncludeToFeed bool `json:"can_include_to_feed,omitempty"` + CoverIsLast int `json:"thumb_is_last,omitempty"` +} diff --git a/responses/contact.go b/responses/contact.go new file mode 100644 index 0000000..56b906b --- /dev/null +++ b/responses/contact.go @@ -0,0 +1,14 @@ +package responses + +type Contact struct { + ID int `json:"id,omitempty"` + UserID int `json:"user_id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"desc,omitempty"` + Phone string `json:"phone,omitempty"` + EMail string `json:"email,omitempty"` + CanWrite bool `json:"can_write,omitempty"` + LastSeenStatus int `json:"last_seen_status,omitempty"` + Photo50 int `json:"photo_50,omitempty"` + CallsID int `json:"calls_id,omitempty"` +} diff --git a/responses/error.go b/responses/error.go new file mode 100644 index 0000000..ea8a527 --- /dev/null +++ b/responses/error.go @@ -0,0 +1,18 @@ +package responses + +const InternalErrorCode = 1512 + +type Error struct { + Code int `json:"error_code,omitempty"` + Message string `json:"error_msg,omitempty"` + Params []ErrorParam `json:"request_params,omitempty"` +} + +type ErrorParam struct { + Key string `json:"key,omitempty"` + Value string `json:"value,omitempty"` +} + +func (e Error) Error() string { + return e.Message +} diff --git a/responses/execute.go b/responses/execute.go new file mode 100644 index 0000000..aa2f029 --- /dev/null +++ b/responses/execute.go @@ -0,0 +1,6 @@ +package responses + +type Execute struct { + ErrorInterface + Result any `json:"response,omitempty"` +} diff --git a/responses/friends.go b/responses/friends.go new file mode 100644 index 0000000..666b88d --- /dev/null +++ b/responses/friends.go @@ -0,0 +1,101 @@ +package responses + +// AddFriendsList + +type AddFriendsListReply struct { + ErrorInterface + Response AddFriendsList `json:"response,omitempty"` +} + +type AddFriendsList struct { + ListID int `json:"list_id,omitempty"` +} + +// AreFriends + +type AreFriendsReply struct { + ErrorInterface + Response []AreFriend `json:"response,omitempty"` +} + +type AreFriend struct { + UserID int `json:"user_id,omitempty"` + FriendStatus int `json:"friend_status,omitempty"` + IsRequestUnread bool `json:"is_request_unread,omitempty"` + Sign string `json:"sign,omitempty"` +} + +// DeleteFriend + +type DeleteFriendReply struct { + ErrorInterface + Response DeleteFriend `json:"response,omitempty"` +} + +type DeleteFriend struct { + Success int `json:"success,omitempty"` + FriendDeleted int `json:"friend_deleted,omitempty"` + InRequestDeleted int `json:"in_request_deleted,omitempty"` + OutRequestDeleted int `json:"out_request_deleted,omitempty"` + SuggestionDeleted int `json:"suggestion_deleted,omitempty"` +} + +// GetFriends + +type FriendsReply struct { + ErrorInterface + Response Friends `json:"response,omitempty"` +} + +type Friends struct { + Friends []User `json:"items,omitempty"` +} + +// GetFriendsLists + +type FriendsListsReply struct { + ErrorInterface + Response FriendsLists `json:"response,omitempty"` +} + +type FriendsLists struct { + Count int `json:"count,omitempty"` + Items []FriendsListItem `json:"items,omitempty"` +} + +type FriendsListItem struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +// GetMutualFriends + +type MutualFriendsReply struct { + ErrorInterface + Response []MutualFriend `json:"response,omitempty"` +} + +type MutualFriend struct { + CommonCount int `json:"common_count,omitempty"` + CommonFriends []int `json:"common_friends,omitempty"` + ID int `json:"id,omitempty"` +} + +// GetOnlineFriends + +type OnlineFriendsReply struct { + ErrorInterface + Response OnlineFriends `json:"response,omitempty"` +} + +type OnlineFriends struct { + Online []int `json:"online,omitempty"` + OnlineMobile []int `json:"online_mobile,omitempty"` +} + +// GetRecentFriends + +type RecentFriendsReply struct { + ErrorInterface + Response []int `json:"response,omitempty"` +} diff --git a/responses/general.go b/responses/general.go new file mode 100644 index 0000000..559a3f6 --- /dev/null +++ b/responses/general.go @@ -0,0 +1,32 @@ +package responses + +type Response interface { + GetError() *Error +} + +type ErrorInterface struct { + Error *Error `json:"error"` +} + +func (r *ErrorInterface) GetError() *Error { + return r.Error +} + +type OperationCode struct { + ErrorInterface + Code int `json:"response,omitempty"` +} + +type ResultOperationCodeReply struct { + ErrorInterface + Response ResultOperationCode `json:"response,omitempty"` +} + +type ResultOperationCode struct { + Result int `json:"result,omitempty"` +} + +type Item struct { + ID int `json:"id"` + Name string `json:"name"` +} diff --git a/responses/gifts.go b/responses/gifts.go new file mode 100644 index 0000000..06dba8b --- /dev/null +++ b/responses/gifts.go @@ -0,0 +1,27 @@ +package responses + +type GiftsReply struct { + ErrorInterface + Response Gifts `json:"response,omitempty"` +} + +type Gifts struct { + Count int `json:"count,omitempty"` + Gifts []Gift `json:"items,omitempty"` +} + +type Gift struct { + ID int `json:"id,omitempty"` + UserID int `json:"from_id,omitempty"` + Message string `json:"message,omitempty"` + Date int `json:"date,omitempty"` + Gift GiftInfo `json:"gift,omitempty"` + Privacy int `json:"privacy,omitempty"` +} + +type GiftInfo struct { + ID int `json:"id,omitempty"` + Photo48 string `json:"thumb_48,omitempty"` + Photo96 string `json:"thumb_96,omitempty"` + Photo256 string `json:"thumb_256,omitempty"` +} diff --git a/responses/groups.go b/responses/groups.go new file mode 100644 index 0000000..bf2ad77 --- /dev/null +++ b/responses/groups.go @@ -0,0 +1,780 @@ +package responses + +import "github.com/aejoy/vkgo/update" + +// AddGroupAddress + +type AddGroupAddressReply struct { + ErrorInterface + Response AddGroupAddress `json:"response,omitempty"` +} + +type AddGroupAddress struct { + ID int `json:"id,omitempty"` + Address string `json:"address,omitempty"` + CityID int `json:"city_id,omitempty"` + CountryID int `json:"country_id,omitempty"` + City City `json:"city,omitempty"` + Country Country `json:"country,omitempty"` + Latitude float64 `json:"latitude,omitempty"` + Longitude float64 `json:"longitude,omitempty"` + OpenStatus OpenStatus `json:"open_status,omitempty"` + Title string `json:"title,omitempty"` + WorkInfoStatus string `json:"work_info_status,omitempty"` +} + +type OpenStatus struct { + Style string `json:"style,omitempty"` + PrimaryText string `json:"primary_text,omitempty"` + SecondaryText string `json:"secondary_text,omitempty"` +} + +// AddGroupCallbackServer + +type AddGroupCallbackServerReply struct { + ErrorInterface + Response AddGroupCallbackServer `json:"response,omitempty"` +} + +type AddGroupCallbackServer struct { + ServerID int `json:"server_id,omitempty"` +} + +// AddGroupLink + +type AddGroupLinkReply struct { + Response AddGroupLink `json:"response,omitempty"` +} + +type AddGroupLink struct { + ID int `json:"id,omitempty"` + URL string `json:"url,omitempty"` + Name string `json:"name,omitempty"` + EditTitle int `json:"edit_title,omitempty"` + Desc string `json:"desc,omitempty"` + Photo100 string `json:"photo_100,omitempty"` + Photo50 string `json:"photo_50,omitempty"` +} + +// ApproveRequestGroup +// CreateGroup + +type CreateGroup struct { + ErrorInterface + Response Group `json:"response,omitempty"` +} + +// EditGroupManager + +type EditGroupManagerReply struct { + ErrorInterface + Response EditGroupManager `json:"response,omitempty"` +} + +type EditGroupManager struct { + Status string `json:"status"` +} + +// GetUserGroups + +type UserGroupsReply struct { + ErrorInterface + Response UserGroups `json:"response,omitempty"` +} + +type UserGroups struct { + Groups []Group `json:"items,omitempty"` +} + +// GetGroup + +type GroupsReply struct { + ErrorInterface + Response Groups `json:"response,omitempty"` +} + +type Groups struct { + Groups []Group `json:"groups,omitempty"` +} + +type Group struct { + ErrorInterface + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Domain string `json:"screen_name,omitempty"` + IsClosed int `json:"is_closed,omitempty"` + Deactivated string `json:"deactivated,omitempty"` + IsAdmin int `json:"is_admin,omitempty"` + AdminLevel int `json:"admin_level,omitempty"` + IsMember int `json:"is_member,omitempty"` + IsAdvertiser int `json:"is_advertiser,omitempty"` + InvitedBy int `json:"invited_by,omitempty"` + Type string `json:"type,omitempty"` + Photo50 string `json:"photo_50,omitempty"` + Photo100 string `json:"photo_100,omitempty"` + Photo200 string `json:"photo_200,omitempty"` + Activity string `json:"activity,omitempty"` + Addresses Addresses `json:"addresses,omitempty"` + AgeLimits int `json:"age_limits,omitempty"` + BanInfo BanInfo `json:"ban_info,omitempty"` + CanCreateTopic int `json:"can_create_topic,omitempty"` + CanMessage int `json:"can_message,omitempty"` + CanPost int `json:"can_post,omitempty"` + CanSuggest int `json:"can_suggest,omitempty"` + CanSeeAllPosts int `json:"can_see_all_posts,omitempty"` + CanUploadDoc int `json:"can_upload_doc,omitempty"` + CanUploadStory int `json:"can_upload_story,omitempty"` + CanUploadVideo int `json:"can_upload_video,omitempty"` + City City `json:"city,omitempty"` + Contacts []Contact `json:"contacts,omitempty"` + Counters Counters `json:"counters,omitempty"` + Country Country `json:"country,omitempty"` + Cover Cover `json:"cover,omitempty"` + CropPhoto CropPhoto `json:"crop_photo,omitempty"` + Description string `json:"description,omitempty"` + PinnedPost int `json:"fixed_post,omitempty"` + HasPhoto int `json:"has_photo,omitempty"` + IsFavorite int `json:"is_favorite,omitempty"` + IsHiddenFromFeed int `json:"is_hidden_from_feed,omitempty"` + IsMessagesBlocked int `json:"is_messages_blocked,omitempty"` + Links []Link `json:"links,omitempty"` + MainAlbumID int `json:"main_album_id,omitempty"` + MainSection int `json:"main_section,omitempty"` + Market Market `json:"market,omitempty"` + MemberStatus int `json:"member_status,omitempty"` + MembersCount int `json:"members_count,omitempty"` + Place Place `json:"place,omitempty"` + PublicDateLabel string `json:"public_date_label,omitempty"` + Site string `json:"site,omitempty"` + StartDate any `json:"start_date,omitempty"` + FinishDate string `json:"finish_date,omitempty"` + Status string `json:"status,omitempty"` + Trending int `json:"trending,omitempty"` + Verified int `json:"verified,omitempty"` + Wall int `json:"wall,omitempty"` + WikiPage string `json:"wiki_page,omitempty"` + + // without documentation + // Like Like `json:"like,omitempty"` + DeactivatedMessage string `json:"deactivated_message,omitempty"` + DeactivatedType string `json:"deactivated_type,omitempty"` +} + +type Addresses struct { + IsEnabled bool `json:"is_enabled,omitempty"` + MainAddressID int `json:"main_address_id,omitempty"` + MainAddress MainAddress `json:"main_address"` +} + +type MainAddress struct { + ID int `json:"id,omitempty"` + Address string `json:"address,omitempty"` + City City `json:"city,omitempty"` + Country Country `json:"country,omitempty"` + Title string `json:"title,omitempty"` + WorkInfoStatus string `json:"work_info_status,omitempty"` +} + +type Like struct { + Liked bool `json:"is_liked,omitempty"` + Friends FriendsLike `json:"friends,omitempty"` +} + +type FriendsLike struct { + Count int `json:"count,omitempty"` + Preview any `json:"preview,omitempty"` +} + +type BanInfo struct { + EndDate int `json:"end_date,omitempty"` + Comment string `json:"comment,omitempty"` +} + +type Country struct { + ID int `json:"id,omitempty"` + Title string `json:"title,omitempty"` +} + +type City struct { + ID int `json:"id,omitempty"` + Title string `json:"title,omitempty"` +} + +type Counter struct { + Albums int `json:"albums,omitempty"` + Market int `json:"market,omitempty"` + Photos int `json:"photos,omitempty"` + Topics int `json:"topics,omitempty"` + Articles int `json:"articles,omitempty"` + Narratives int `json:"narratives,omitempty"` + ClassifiedYoula int `json:"classified_youla,omitempty"` +} + +type Cover struct { + Enabled int `json:"enabled,omitempty"` + Images []update.PhotoSize `json:"images,omitempty"` + OriginalImage update.PhotoSize `json:"original_image,omitempty"` + PhotoID int `json:"photo_id"` +} + +type CropPhoto struct { + Photo update.Photo `json:"photo,omitempty"` + Crop Crop `json:"crop,omitempty"` + Rect Crop `json:"rect,omitempty"` +} + +type Crop struct { + X any `json:"x,omitempty"` + Y any `json:"y,omitempty"` + X2 any `json:"x2,omitempty"` + Y2 any `json:"y2,omitempty"` +} + +type Link struct { + ID int `json:"id,omitempty"` + URL string `json:"url,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"desc,omitempty"` + Photo50 string `json:"photo_50,omitempty"` + Photo100 string `json:"photo_100,omitempty"` +} + +type Market struct { + Enabled int `json:"enabled,omitempty"` + Buttons Buttons `json:"buttons"` + ShopConditions StopConditions `json:"shop_conditions"` + ViewedProductsEnabled bool `json:"viewed_products_enabled"` + + IsHsEnabled bool `json:"is_hs_enabled"` + Type string `json:"type,omitempty"` + PriceMax string `json:"price_max,omitempty"` + PriceMin string `json:"price_min,omitempty"` + MainAlbumID int `json:"main_album_id,omitempty"` + ContactID int `json:"contact_id,omitempty"` + Currency Currency `json:"currency,omitempty"` + Symbol string `json:"currency_text,omitempty"` + + // without documentation + IsShowHeaderItemsLink int `json:"is_show_header_items_link,omitempty"` + IsUseSimplifiedShowcase bool `json:"is_use_simplified_showcase,omitempty"` + HasNotInMarketTab bool `json:"has_not_in_market_tab,omitempty"` + HasModerationRejectedTab bool `json:"has_moderation_rejected_tab,omitempty"` + UnviewedOrdersCount int `json:"unviewed_orders_count,omitempty"` + // CommunityManageEnabled int `json:"is_community_manage_enabled,omitempty"` +} + +type Buttons struct { + ButtonTypeWritePreset ButtonTypeWritePreset `json:"button_type_write_preset,omitempty"` + ButtonTypeOpenPreset ButtonTypeOpenPreset `json:"button_type_open_preset,omitempty"` + ButtonType []ButtonType `json:"button_type,omitempty"` + ButtonTypeCallPreset ButtonTypeCallPreset `json:"button_type_call_preset,omitempty"` + Buttons []interface{} `json:"buttons,omitempty"` +} + +type ButtonTypeWritePreset struct { + Recipients []ButtonRecipient `json:"recipients,omitempty"` + ButtonTitles []ButtonTitle `json:"button_titles,omitempty"` +} + +type ButtonTypeOpenPreset struct { + ButtonTitles []ButtonTitle `json:"button_titles,omitempty"` +} + +type ButtonType struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type ButtonTypeCallPreset struct { + ValidationRegex string `json:"validation_regex,omitempty"` + ValidationRegexErrorMsg string `json:"validation_regex_error_msg,omitempty"` + Timezones []Timezone `json:"timezones,omitempty"` + Weekdays []Weekday `json:"weekdays,omitempty"` +} + +type Timezone struct { + Timezone string `json:"timezone,omitempty"` + Name string `json:"name,omitempty"` +} + +type Weekday struct { + Weekday string `json:"weekday,omitempty"` + Name string `json:"name,omitempty"` +} + +type ButtonRecipient struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type ButtonTitle struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + IsDisabled bool `json:"is_disabled,omitempty"` +} + +type StopConditions struct { + Fields StopConditionsFields `json:"fields,omitempty"` + Header string `json:"header,omitempty"` + Buttons []StopConditionsButtons `json:"buttons,omitempty"` + IntegrationType string `json:"integration_type,omitempty"` +} + +type StopConditionsFields struct { + Delivery FieldsItem `json:"delivery,omitempty"` + Payment FieldsItem `json:"payment,omitempty"` + Refund FieldsItem `json:"refund,omitempty"` +} + +type StopConditionsButtons struct { + Action StopConditionsAction `json:"action,omitempty"` + Title string `json:"title,omitempty"` +} + +type StopConditionsAction struct { + Type string `json:"type,omitempty"` + PerformActionWithURL PerformActionWithURL `json:"perform_action_with_url,omitempty"` + URL string `json:"url,omitempty"` +} + +type PerformActionWithURL struct { + Action string `json:"action,omitempty"` +} + +type FieldsItem struct { + Title string `json:"title,omitempty"` + Text string `json:"text,omitempty"` + OnEmptyText string `json:"on_empty_text,omitempty"` +} + +type Currency struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Symbol string `json:"title,omitempty"` +} + +type Place struct { + ID int `json:"id,omitempty"` + Title string `json:"title,omitempty"` + Latitude any `json:"latitude,omitempty"` + Longitude any `json:"longitude,omitempty"` + Type string `json:"type,omitempty"` + CountryID int `json:"country,omitempty"` + CityID int `json:"city,omitempty"` + Address string `json:"address,omitempty"` +} + +// GetBannedUsers + +type BannedUsersReply struct { + ErrorInterface + Response BannedUsers `json:"response,omitempty"` +} + +type BannedUsers struct { + Count int `json:"count,omitempty"` + Bans []BannedUserResponse `json:"items,omitempty"` +} + +type BannedUserResponse struct { + ErrorInterface + Type string `json:"type,omitempty"` + Info InfoBanUser `json:"ban_info,omitempty"` + Profile User `json:"profile,omitempty"` +} + +type InfoBanUser struct { + AdminID int `json:"admin_id,omitempty"` + Comment string `json:"comment,omitempty"` + ShowComment bool `json:"comment_visible,omitempty"` + Date int `json:"date,omitempty"` + EndDate int `json:"end_date,omitempty"` + Reason int `json:"reason,omitempty"` +} + +// GetGroupCallbackConfirmationCode + +type GroupCallbackConfirmationCodeReply struct { + ErrorInterface + Response GroupCallbackConfirmationCode `json:"response,omitempty"` +} + +type GroupCallbackConfirmationCode struct { + Code string `json:"code,omitempty"` +} + +// GetGroupCallbackServers + +type GroupCallbackServersReply struct { + ErrorInterface + Response GroupCallbackServers `json:"response,omitempty"` +} + +type GroupCallbackServers struct { + Count int `json:"count,omitempty"` + Items []GroupCallbackServer `json:"items,omitempty"` +} + +type GroupCallbackServer struct { + ID int `json:"id,omitempty"` + Title string `json:"title,omitempty"` + CreatorID int `json:"creator_id,omitempty"` + URL string `json:"url,omitempty"` + SecretKey string `json:"secret_key,omitempty"` + Status string `json:"status,omitempty"` +} + +// GetGroupCallbackSettings + +type GroupCallbackSettingsReply struct { + ErrorInterface + Response GroupCallbackSettings `json:"response,omitempty"` +} + +type GroupCallbackSettings struct { + APIVersion string `json:"api_version,omitempty"` + Events SettingsEvents `json:"events,omitempty"` +} + +type SettingsEvents struct { + AppPayload int `json:"app_payload,omitempty"` + AudioNew int `json:"audio_new,omitempty"` + BoardPostDelete int `json:"board_post_delete,omitempty"` + BoardPostEdit int `json:"board_post_edit,omitempty"` + BoardPostNew int `json:"board_post_new,omitempty"` + BoardPostRestore int `json:"board_post_restore,omitempty"` + GroupChangePhoto int `json:"group_change_photo,omitempty"` + GroupChangeSettings int `json:"group_change_settings,omitempty"` + GroupJoin int `json:"group_join,omitempty"` + GroupLeave int `json:"group_leave,omitempty"` + GroupOfficersEdit int `json:"group_officers_edit,omitempty"` + MarketCommentDelete int `json:"market_comment_delete,omitempty"` + MarketCommentEdit int `json:"market_comment_edit,omitempty"` + MarketCommentNew int `json:"market_comment_new,omitempty"` + MarketCommentRestore int `json:"market_comment_restore,omitempty"` + MessageAllow int `json:"message_allow,omitempty"` + MessageDeny int `json:"message_deny,omitempty"` + MessageNew int `json:"message_new,omitempty"` + MessageReply int `json:"message_reply,omitempty"` + MessageEdit int `json:"message_edit,omitempty"` + PhotoCommentDelete int `json:"photo_comment_delete,omitempty"` + PhotoCommentEdit int `json:"photo_comment_edit,omitempty"` + PhotoCommentNew int `json:"photo_comment_new,omitempty"` + PhotoCommentRestore int `json:"photo_comment_restore,omitempty"` + PhotoNew int `json:"photo_new,omitempty"` + PollVoteNew int `json:"poll_vote_new,omitempty"` + UserBlock int `json:"user_block,omitempty"` + UserUnblock int `json:"user_unblock,omitempty"` + VideoCommentDelete int `json:"video_comment_delete,omitempty"` + VideoCommentEdit int `json:"video_comment_edit,omitempty"` + VideoCommentNew int `json:"video_comment_new,omitempty"` + VideoCommentRestore int `json:"video_comment_restore,omitempty"` + VideoNew int `json:"video_new,omitempty"` + MessageReactionEvent int `json:"message_reaction_event,omitempty"` + WallPostNew int `json:"wall_post_new,omitempty"` + WallReplyDelete int `json:"wall_reply_delete,omitempty"` + WallReplyEdit int `json:"wall_reply_edit,omitempty"` + WallReplyNew int `json:"wall_reply_new,omitempty"` + WallReplyRestore int `json:"wall_reply_restore,omitempty"` + WallRepost int `json:"wall_repost,omitempty"` + WallSchedulePostNew int `json:"wall_schedule_post_new,omitempty"` + WallSchedulePostDelete int `json:"wall_schedule_post_delete,omitempty"` + LeadFormsNew int `json:"lead_forms_new,omitempty"` + LikeAdd int `json:"like_add,omitempty"` + LikeRemove int `json:"like_remove,omitempty"` + MarketOrderNew int `json:"market_order_new,omitempty"` + MarketOrderEdit int `json:"market_order_edit,omitempty"` + MessageRead int `json:"message_read,omitempty"` + MessageTypingState int `json:"message_typing_state,omitempty"` + VkpayTransaction int `json:"vkpay_transaction,omitempty"` + MessageEvent int `json:"message_event,omitempty"` + DonutSubscriptionCreate int `json:"donut_subscription_create,omitempty"` + DonutSubscriptionProlonged int `json:"donut_subscription_prolonged,omitempty"` + DonutSubscriptionCancelled int `json:"donut_subscription_cancelled,omitempty"` + DonutSubscriptionExpired int `json:"donut_subscription_expired,omitempty"` + DonutSubscriptionPriceChanged int `json:"donut_subscription_price_changed,omitempty"` + DonutMoneyWithdraw int `json:"donut_money_withdraw,omitempty"` + DonutMoneyWithdrawError int `json:"donut_money_withdraw_error,omitempty"` + MusicSubscriptionUpdate int `json:"music_subscription_update,omitempty"` + InappSubscriptionUpdate int `json:"inapp_subscription_update,omitempty"` + InappOrderCreate int `json:"inapp_order_create,omitempty"` + InappOrderRefund int `json:"inapp_order_refund,omitempty"` +} + +type GroupCatalogInfoReply struct { + ErrorInterface + Response GroupCatalogInfo `json:"response,omitempty"` +} + +type GroupCatalogInfo struct { + Enabled int `json:"enabled,omitempty"` + Categories []GroupCatalogInfoCategory `json:"categories,omitempty"` + Subcategories []Subcategory `json:"subcategories,omitempty"` +} + +type GroupCatalogInfoCategory struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + PageCount int `json:"page_count,omitempty"` + PagePreviews []GroupCatalogInfoPagePreview `json:"page_previews,omitempty"` +} + +type GroupCatalogInfoPagePreview struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + ScreenName string `json:"screen_name,omitempty"` + IsClosed int `json:"is_closed,omitempty"` + Type string `json:"type,omitempty"` + IsAdmin int `json:"is_admin,omitempty"` + IsMember int `json:"is_member,omitempty"` + IsAdvertiser int `json:"is_advertiser,omitempty"` + Photo50 string `json:"photo_50,omitempty"` + Photo100 string `json:"photo_100,omitempty"` + Photo200 string `json:"photo_200,omitempty"` +} + +type Subcategory struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Genders []Gender `json:"genders,omitempty"` +} + +type Gender struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +// GetGroupInvitedUsers + +type GroupInvitedUsers struct { + Response GroupInvitedUser `json:"response,omitempty"` +} + +type GroupInvitedUser struct { + Items []User `json:"items,omitempty"` +} + +// GetGroupInvites + +type GroupInvitesReply struct { + ErrorInterface + Response GroupInvites `json:"response,omitempty"` +} + +type GroupInvites struct { + Count int `json:"count,omitempty"` + Items []Group `json:"items,omitempty"` + Users []User `json:"profiles,omitempty"` + Groups []Group `json:"groups,omitempty"` +} + +// GetGroupLongPollServer + +type LongPollServerReply struct { + ErrorInterface + Response LongPollServer `json:"response,omitempty"` +} + +type LongPollServer struct { + Server string `json:"server,omitempty"` + Key string `json:"key,omitempty"` + TS any `json:"ts,omitempty"` + PTS any `json:"pts,omitempty"` + Version int `json:"version,omitempty"` +} + +// GetGroupLongPollSettings + +type LongPollSettingsReply struct { + ErrorInterface + Response LongPollSettings `json:"response,omitempty"` +} + +type LongPollSettings struct { + Events SettingsEvents `json:"events,omitempty"` + IsEnabled bool `json:"is_enabled,omitempty"` + APIVersion string `json:"api_version,omitempty"` +} + +// GetGroupMembers + +type GroupMembersReply struct { + ErrorInterface + Response GroupMembers `json:"response,omitempty"` +} + +type GroupMembers struct { + Count int `json:"count,omitempty"` + Items []GroupMember `json:"items,omitempty"` + NextFrom string `json:"next_from,omitempty"` +} + +type GroupMember struct { + ID int `json:"id,omitempty"` + FirstName string `json:"first_name,omitempty"` + LastName string `json:"last_name,omitempty"` + CanAccessClosed bool `json:"can_access_closed,omitempty"` + IsClosed bool `json:"is_closed,omitempty"` + Deactivated string `json:"deactivated,omitempty"` +} + +// GetGroupOnlineStatus + +type GroupOnlineStatusReply struct { + ErrorInterface + Response GroupOnlineStatus `json:"response,omitempty"` +} + +type GroupOnlineStatus struct { + Status string `json:"status,omitempty"` +} + +// GetGroupRequests + +type GroupRequestsReply struct { + ErrorInterface + Response GroupRequests `json:"response,omitempty"` +} + +type GroupRequests struct { + Items []User `json:"items,omitempty"` +} + +// GetGroupSettings + +type GroupSettingsReply struct { + ErrorInterface + Response GroupSettings `json:"response,omitempty"` +} + +type GroupSettings struct { + Audio int `json:"audio,omitempty"` + Articles int `json:"articles,omitempty"` + CityID int `json:"city_id,omitempty"` + CityName string `json:"city_name,omitempty"` + Description string `json:"description,omitempty"` + Docs int `json:"docs,omitempty"` + Messages int `json:"messages,omitempty"` + ObsceneFilter int `json:"obscene_filter,omitempty"` + ObsceneStopwords int `json:"obscene_stopwords,omitempty"` + ToxicFilter int `json:"toxic_filter,omitempty"` + DisableRepliesFromGroups int `json:"disable_replies_from_groups,omitempty"` + Photos int `json:"photos,omitempty"` + Title string `json:"title,omitempty"` + Topics int `json:"topics,omitempty"` + Video int `json:"video,omitempty"` + Wall int `json:"wall,omitempty"` + Wiki int `json:"wiki,omitempty"` + Access int `json:"access,omitempty"` + ActionButton ActionButton `json:"action_button,omitempty"` + Address string `json:"address,omitempty"` + RecognizePhoto int `json:"recognize_photo,omitempty"` + Contacts int `json:"contacts,omitempty"` + Links int `json:"links,omitempty"` + LiveCovers LiveCovers `json:"live_covers,omitempty"` + SectionsList []Section `json:"sections_list,omitempty"` + MainSection int `json:"main_section,omitempty"` + SecondarySection int `json:"secondary_section,omitempty"` + AgeLimits int `json:"age_limits,omitempty"` + CountryID int `json:"country_id,omitempty"` + CountryName string `json:"country_name,omitempty"` + Events int `json:"events,omitempty"` + Market Market `json:"market,omitempty"` + MarketServices MarketServices `json:"market_services,omitempty"` + Narratives int `json:"narratives,omitempty"` + BotsCapabilities int `json:"bots_capabilities,omitempty"` + BotsStartButton int `json:"bots_start_button,omitempty"` + BotsAddToChat int `json:"bots_add_to_chat,omitempty"` + Clips int `json:"clips,omitempty"` + Textlives int `json:"textlives,omitempty"` + ObsceneWords []any `json:"obscene_words,omitempty"` + PublicCategory int `json:"public_category,omitempty"` + PublicCategoryList []PublicCategory `json:"public_category_list,omitempty"` + PublicSubcategory int `json:"public_subcategory,omitempty"` + SuggestedPrivacy int `json:"suggested_privacy,omitempty"` + Website string `json:"website,omitempty"` + Phone string `json:"phone,omitempty"` + EnableReplies int `json:"enable_replies,omitempty"` + IsSuggestedPostEnabled bool `json:"is_suggested_post_enabled,omitempty"` +} + +type ActionButton struct { + IsEnabled bool `json:"is_enabled,omitempty"` +} + +type LiveCovers struct { + IsEnabled bool `json:"is_enabled,omitempty"` +} + +type Section struct { + ID int `json:"id,omitempty"` + Title string `json:"title,omitempty"` +} + +type MarketServices struct { + Enabled bool `json:"enabled,omitempty"` + CanMessage bool `json:"can_message,omitempty"` + CommentsEnabled bool `json:"comments_enabled,omitempty"` + ContactID int `json:"contact_id,omitempty"` + Currency Currency `json:"currency,omitempty"` + ViewType ViewType `json:"view_type,omitempty"` + BlockName BlockName `json:"block_name,omitempty"` + ButtonLabel ButtonLabel `json:"button_label,omitempty"` +} + +type BlockName struct { + SelectedItemID int `json:"selected_item_id,omitempty"` + Items []Item `json:"items,omitempty"` +} + +type ButtonLabel struct { + SelectedItemID int `json:"selected_item_id,omitempty"` + Items []ButtonLabelItem `json:"items,omitempty"` +} + +type ButtonLabelItem struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + IsDisabled bool `json:"is_disabled,omitempty"` +} + +type ViewType struct { + SelectedItemID int `json:"selected_item_id,omitempty"` + Items []Item `json:"items,omitempty"` +} + +type PublicCategory struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Subcategories []Subcategory `json:"subcategories,omitempty"` +} + +// GetGroupTokenPermissions + +type GroupTokenPermissionsReply struct { + ErrorInterface + Response GroupTokenPermissions `json:"response,omitempty"` +} + +type GroupTokenPermissions struct { + Mask int `json:"mask,omitempty"` + Permissions []GroupTokenPermission `json:"permissions,omitempty"` +} + +type GroupTokenPermission struct { + Name string `json:"name,omitempty"` + Setting int `json:"setting,omitempty"` +} + +// InviteGroup +// IsGroupMember + +type IsGroupMemberReply struct { + ErrorInterface + Response IsGroupMember `json:"response,omitempty"` +} + +type IsGroupMember struct { + Member int `json:"member,omitempty"` + CanInvite int `json:"can_invite,omitempty"` +} diff --git a/responses/health.go b/responses/health.go new file mode 100644 index 0000000..8f51a3f --- /dev/null +++ b/responses/health.go @@ -0,0 +1,17 @@ +package responses + +type HealthReply struct { + ErrorInterface + Response Health `json:"response"` +} + +type Health struct { + Statuses []HealthStatus `json:"health_statuses,omitempty"` +} + +type HealthStatus struct { + AverageTime int `json:"average_response_time,omitempty"` + Category string `json:"category,omitempty"` + Status string `json:"status,omitempty"` + Uptime any `json:"uptime,omitempty"` +} diff --git a/responses/historyMessages.go b/responses/historyMessages.go new file mode 100644 index 0000000..32d3372 --- /dev/null +++ b/responses/historyMessages.go @@ -0,0 +1,16 @@ +package responses + +import "github.com/aejoy/vkgo/update" + +type HistoryMessagesReply struct { + ErrorInterface + Response HistoryMessages `json:"response"` +} + +type HistoryMessages struct { + Count int `json:"count,omitempty"` + Messages []update.Message `json:"items,omitempty"` + Users []User `json:"profiles,omitempty"` + Chats []Conversation `json:"conversations,omitempty"` + Contacts []Contact `json:"contacts,omitempty"` +} diff --git a/responses/likes.go b/responses/likes.go new file mode 100644 index 0000000..239f943 --- /dev/null +++ b/responses/likes.go @@ -0,0 +1,46 @@ +package responses + +// AddLike +// DeleteLike + +type LikeActionReply struct { + ErrorInterface + Response LikeAction `json:"response,omitempty"` +} + +type LikeAction struct { + Likes int `json:"likes,omitempty"` + Reactions Reactions `json:"reactions,omitempty"` +} + +type Reactions struct { + Items []ReactionItem `json:"items,omitempty"` + UserReaction int `json:"user_reaction,omitempty"` +} + +type ReactionItem struct { + ID int `json:"id,omitempty"` + Count int `json:"count,omitempty"` +} + +// GetLikes + +type LikesReply struct { + ErrorInterface + Response Likes `json:"response,omitempty"` +} + +type Likes struct { + Users []User `json:"items,omitempty"` +} + +type IsLikedReply struct { + ErrorInterface + Response IsLiked `json:"response,omitempty"` +} + +type IsLiked struct { + Liked int `json:"liked,omitempty"` + Copied int `json:"copied,omitempty"` + ReactionID int `json:"reaction_id,omitempty"` +} diff --git a/responses/messages.go b/responses/messages.go new file mode 100644 index 0000000..240707c --- /dev/null +++ b/responses/messages.go @@ -0,0 +1,305 @@ +package responses + +import "github.com/aejoy/vkgo/update" + +type CreateChatReply struct { + ErrorInterface + Response CreateChat ` json:"response"` +} + +type CreateChat struct { + ChatID int `json:"chat_id,omitempty"` + Users []int `json:"peer_ids,omitempty"` +} + +type DeleteMessages struct { + ErrorInterface + Messages []DeleteMessage `json:"response,omitempty"` +} + +type DeleteMessage struct { + ChatID int `json:"peer_id,omitempty"` + MessageID int `json:"message_id,omitempty"` + ChatMessageID int `json:"conversation_message_id,omitempty"` + Response int `json:"response,omitempty"` +} + +type DeleteChatPhotoReply struct { + ErrorInterface + Response DeleteChatPhoto `json:"response,omitempty"` +} + +type DeleteChatPhoto struct { + MessageID int `json:"message_id,omitempty"` + Chat Chat `json:"chat,omitempty"` +} + +type Chat struct { + ID int `json:"id,omitempty"` + Type string `json:"type,omitempty"` + Title string `json:"title,omitempty"` + AdminID int `json:"admin_id,omitempty"` + Users []int `json:"users,omitempty"` + PushSettings PushSettings `json:"push_settings,omitempty"` + Photo50 string `json:"photo_50,omitempty"` + Photo100 string `json:"photo_100,omitempty"` + Photo200 string `json:"photo_200,omitempty"` + PhotoBase string `json:"photo_base,omitempty"` + Left int `json:"left,omitempty"` + Kicked int `json:"kicked,omitempty"` + + // without documentation + MembersCount int `json:"members_count,omitempty"` + IsDefaultPhoto bool `json:"is_default_photo,omitempty"` +} + +type DeleteChatReply struct { + ErrorInterface + Response DeleteChat `json:"response,omitempty"` +} + +type DeleteChat struct { + LastDeletedID int `json:"last_deleted_id,omitempty"` +} + +type ChatMessagesReply struct { + ErrorInterface + Response ChatMessages `json:"response,omitempty"` +} + +type ChatMessages struct { + Messages []update.Message `json:"items,omitempty"` +} + +type MessagesReply struct { + ErrorInterface + Response Messages `json:"response,omitempty"` +} + +type Messages struct { + Messages []update.Message `json:"items,omitempty"` + Users []User `json:"profiles,omitempty"` + Groups []Group `json:"groups,omitempty"` +} + +type ChatMembersReply struct { + ErrorInterface + Response ChatMembers `json:"response,omitempty"` +} + +type ChatMembers struct { + Settings ChatRestrictions `json:"chat_restrictions,omitempty"` + Members []ChatMember `json:"items,omitempty"` + Users []User `json:"profiles,omitempty"` + Groups []Group `json:"groups,omitempty"` + Contacts []Contact `json:"contacts,omitempty"` +} + +type ChatRestrictions struct { + AdminsPromoteUsers bool `json:"admins_promote_users,omitempty"` + OnlyAdminsEditInfo bool `json:"only_admins_edit_info,omitempty"` + OnlyAdminsEditPin bool `json:"only_admins_edit_pin,omitempty"` + OnlyAdminsInvite bool `json:"only_admins_invite,omitempty"` + OnlyAdminsKick bool `json:"only_admins_kick,omitempty"` +} + +type ChatMember struct { + ID int `json:"member_id,omitempty"` + InvitedBy int `json:"invited_by,omitempty"` + IsOwner bool `json:"is_owner,omitempty"` + IsAdmin bool `json:"is_admin,omitempty"` + CanKick bool `json:"can_kick,omitempty"` + JoinDate int `json:"join_date,omitempty"` +} + +type ChatsReply struct { + ErrorInterface + Response Chats ` json:"response,omitempty"` +} + +type Chats struct { + Chats []Conversation `json:"items,omitempty"` + Users []User `json:"profiles,omitempty"` + Groups []Group `json:"groups,omitempty"` +} + +type Conversation struct { + ErrorInterface + Chat ConversationPeer `json:"peer,omitempty"` + InRead int `json:"in_read,omitempty"` + OutRead int `json:"out_read,omitempty"` + UnreadCount int `json:"unread_count,omitempty"` + Important bool `json:"important,omitempty"` + Unanswered bool `json:"unanswered,omitempty"` + PushSettings PushSettings `json:"push_settings,omitempty"` + CanWrite CanWriteChat `json:"can_write,omitempty"` + ChatSettings ChatSettings `json:"chat_settings,omitempty"` + SortID ChatSortID `json:"sort_id,omitempty"` + LastMessageID int `json:"last_message_id,omitempty"` + LastChatMessageID int `json:"last_conversation_message_id,omitempty"` + InReadChatMessageID int `json:"in_read_cmid,omitempty"` + OutReadChatMessageID int `json:"out_read_cmid,omitempty"` + MarkedUnread bool `json:"is_marked_unread,omitempty"` + CanSendMoney bool `json:"can_send_money,omitempty"` + CanReceiveMoney bool `json:"can_receive_money,omitempty"` +} + +type ConversationPeer struct { + ID int `json:"id,omitempty"` + Type string `json:"type,omitempty"` + LocalID int `json:"local_id,omitempty"` +} + +type ChatSortID struct { + MajorID int `json:"major_id,omitempty"` + MinorID int `json:"minor_id,omitempty"` +} + +type CanWriteChat struct { + Allowed bool `json:"allowed,omitempty"` + Reason int `json:"reason,omitempty"` +} + +type ChatSettings struct { + MembersCount int `json:"members_count,omitempty"` + Title string `json:"title,omitempty"` + PinnedMessage PinMessage `json:"pinned_message,omitempty"` + State string `json:"state,omitempty"` + Photo update.PhotoAction `json:"photo,omitempty"` + ActivesID []int `json:"active_ids,omitempty"` + IsGroupChannel bool `json:"is_group_channel,omitempty"` +} + +type IntentUsersReply struct { + ErrorInterface + Response IntentUsers `json:"response"` +} + +type IntentUsers struct { + Items []int `json:"items,omitempty"` + Users []User `json:"profiles,omitempty"` +} + +type ChatLinkReply struct { + ErrorInterface + Response ChatLink ` json:"response,omitempty"` +} + +type ChatLink struct { + Link string `json:"link,omitempty"` +} + +type LastActivityReply struct { + ErrorInterface + Response LastActivity `json:"response,omitempty"` +} + +type LastActivity struct { + Online int `json:"online,omitempty"` + Time int `json:"time,omitempty"` +} + +type MessagesReactionsReply struct { + ErrorInterface + Response MessagesReactions `json:"response,omitempty"` +} + +type MessagesReactions struct { + Items []MessagesReaction `json:"items,omitempty"` +} + +type MessagesReaction struct { + ChatMessageID int `json:"cmid,omitempty"` + Counters []MessageReactionCounter `json:"counters,omitempty"` +} + +type MessageReactionCounter struct { + ReactionID int `json:"reaction_id,omitempty"` + Count int `json:"count,omitempty"` + UserIDs []int `json:"user_ids,omitempty"` +} + +type ReactionaryMessagesReply struct { + ErrorInterface + Response ReactionaryMessages `json:"response,omitempty"` +} + +type ReactionaryMessages struct { + Reactions []ReactionaryMessagesReactions `json:"reactions,omitempty"` + Counters []ReactionaryMessagesCounters `json:"counters"` +} + +type ReactionaryMessagesReactions struct { + UserID int `json:"user_id,omitempty"` + ReactionID int `json:"reaction_id,omitempty"` +} + +type ReactionaryMessagesCounters struct { + ReactionID int `json:"reaction_id,omitempty"` + Count int `json:"count,omitempty"` + UserIDs []int `json:"user_ids,omitempty"` +} + +type ReactionsAssetsReply struct { + ErrorInterface + Response ReactionsAssets `json:"response,omitempty"` +} + +type ReactionsAssets struct { + Version int `json:"version,omitempty"` + Assets []ReactionsAsset `json:"assets,omitempty"` + ReactionIDs []int `json:"reaction_ids,omitempty"` +} + +type ReactionsAsset struct { + ReactionID int `json:"reaction_id,omitempty"` + Links ReactionsAssetLink `json:"links,omitempty"` +} + +type ReactionsAssetLink struct { + BigAnimation string `json:"big_animation,omitempty"` + SmallAnimation string `json:"small_animation,omitempty"` + Static string `json:"static,omitempty"` +} + +type IsMessagesFromGroupAllowedReply struct { + ErrorInterface + Response IsMessagesFromGroupAllowed `json:"response,omitempty"` +} + +type IsMessagesFromGroupAllowed struct { + IsAllowed int `json:"is_allowed,omitempty"` +} + +type JoinChatByInviteLinkReply struct { + ErrorInterface + Response JoinChatByInviteLink `json:"response,omitempty"` +} + +type JoinChatByInviteLink struct { + ChatID int `json:"chat_id,omitempty"` +} + +type PinMessageReply struct { + ErrorInterface + Response PinMessage `json:"response"` +} + +type PinMessage struct { + ID int `json:"id,omitempty"` + Date int `json:"date,omitempty"` + UserID int `json:"from_id,omitempty"` + Text string `json:"text,omitempty"` + Attachments []update.Attachment `json:"attachments,omitempty"` + Geolocation update.Geolocation `json:"geo,omitempty"` + Forwards []string `json:"fwd_messages,omitempty"` +} + +type MuteUserReply struct { + ErrorInterface + Response MuteUser `json:"response"` +} + +type MuteUser struct { + FailedMemberIDs []int `json:"failed_member_ids"` +} diff --git a/responses/photos.go b/responses/photos.go new file mode 100644 index 0000000..dc58a1e --- /dev/null +++ b/responses/photos.go @@ -0,0 +1,12 @@ +package responses + +import "github.com/aejoy/vkgo/update" + +type AlbumPhotosReply struct { + ErrorInterface + Response AlbumPhotos `json:"response"` +} + +type AlbumPhotos struct { + Photos []update.Photo `json:"items"` +} diff --git a/responses/resolveDomain.go b/responses/resolveDomain.go new file mode 100644 index 0000000..a5fd36f --- /dev/null +++ b/responses/resolveDomain.go @@ -0,0 +1,11 @@ +package responses + +type ResolveDomainReply struct { + ErrorInterface + Response ResolveDomain `json:"response"` +} + +type ResolveDomain struct { + Type string `json:"type,omitempty"` + ObjectID int `json:"object_id,omitempty"` +} diff --git a/responses/saveUploadMessagesDocument.go b/responses/saveUploadMessagesDocument.go new file mode 100644 index 0000000..4ee441c --- /dev/null +++ b/responses/saveUploadMessagesDocument.go @@ -0,0 +1,27 @@ +package responses + +type SaveUploadMessagesDocumentReply struct { + ErrorInterface + Response SaveUploadMessagesDocument `json:"response"` +} + +type SaveUploadMessagesDocument struct { + ErrorInterface + Type string `json:"type,omitempty"` + Document SaveUploadMessageDocument `json:"doc,omitempty"` +} + +type SaveUploadMessageDocument struct { + URL string `json:"url,omitempty"` + Date int `json:"date,omitempty"` + ID int `json:"id,omitempty"` + Title string `json:"title,omitempty"` + OwnerID int `json:"owner_id,omitempty"` + Extension string `json:"ext,omitempty"` + Size int `json:"size,omitempty"` +} + +type SaveMessagesDocument struct { + Title string + Tags string +} diff --git a/responses/saveUploadMessagesPhoto.go b/responses/saveUploadMessagesPhoto.go new file mode 100644 index 0000000..3849824 --- /dev/null +++ b/responses/saveUploadMessagesPhoto.go @@ -0,0 +1,31 @@ +package responses + +import "github.com/aejoy/vkgo/update" + +type SaveUploadMessagesPhotoReply struct { + ErrorInterface + Photos []SaveUploadMessagesPhoto `json:"response"` +} + +type SaveUploadMessagesPhoto struct { + Date int `json:"date,omitempty"` + ID int `json:"id,omitempty"` + AlbumID int `json:"album_id,omitempty"` + OwnerID int `json:"owner_id,omitempty"` + AccessKey string `json:"access_key,omitempty"` +} + +type SaveUploadAlbumPhotoReply struct { + ErrorInterface + Response []SaveUploadAlbumPhoto `json:"response"` +} + +type SaveUploadAlbumPhoto struct { + AlbumID int `json:"album_id"` + Date int `json:"date"` + ID int `json:"id"` + OwnerID int `json:"owner_id"` + Sizes []update.PhotoSize `json:"sizes"` + Text string `json:"text"` + HasTags bool `json:"has_tags"` +} diff --git a/responses/sendEventMessage.go b/responses/sendEventMessage.go new file mode 100644 index 0000000..264fbad --- /dev/null +++ b/responses/sendEventMessage.go @@ -0,0 +1,6 @@ +package responses + +type SendEventMessage struct { + ErrorInterface + Code int `json:"response,omitempty"` +} diff --git a/responses/sendMessage.go b/responses/sendMessage.go new file mode 100644 index 0000000..ab13f05 --- /dev/null +++ b/responses/sendMessage.go @@ -0,0 +1,13 @@ +package responses + +type SendMessageReply struct { + ErrorInterface + Response []SendMessage `json:"response"` +} + +type SendMessage struct { + UserID int `json:"user_id,omitempty"` + ChatID int `json:"peer_id,omitempty"` + MessageID int `json:"message_id,omitempty"` + ChatMessageID int `json:"conversation_message_id,omitempty"` +} diff --git a/responses/status.go b/responses/status.go new file mode 100644 index 0000000..52ab937 --- /dev/null +++ b/responses/status.go @@ -0,0 +1,10 @@ +package responses + +type StatusReply struct { + ErrorInterface + Response Status `json:"response"` +} + +type Status struct { + Text string `json:"text,omitempty"` +} diff --git a/responses/storage.go b/responses/storage.go new file mode 100644 index 0000000..837a274 --- /dev/null +++ b/responses/storage.go @@ -0,0 +1,21 @@ +package responses + +type StorageKeysReply struct { + ErrorInterface + Response []string `json:"response,omitempty"` +} + +type StorageReply struct { + ErrorInterface + Response Storages `json:"response,omitempty"` +} + +type Storages []struct { + Key string `json:"key,omitempty"` + Value string `json:"value,omitempty"` +} + +type SetStorageReply struct { + ErrorInterface + Response any `json:"response,omitempty"` +} diff --git a/responses/store.go b/responses/store.go new file mode 100644 index 0000000..2d11031 --- /dev/null +++ b/responses/store.go @@ -0,0 +1,18 @@ +package responses + +type StickersReply struct { + ErrorInterface + Response Stickers `json:"response"` +} + +type Stickers struct { + Stickers []Sticker `json:"items"` +} + +type Sticker struct { + ID int `json:"id"` + Type string `json:"stickers"` + Purchased int `json:"purchased"` + Active int `json:"active"` + Date int `json:"purchase_date"` +} diff --git a/responses/upload.go b/responses/upload.go new file mode 100644 index 0000000..efb13a1 --- /dev/null +++ b/responses/upload.go @@ -0,0 +1,9 @@ +package responses + +import "encoding/json" + +type UploadedFiles []byte + +func (uploadedFiles UploadedFiles) JSON(data any) error { + return json.Unmarshal(uploadedFiles, data) +} diff --git a/responses/uploadFiles.go b/responses/uploadFiles.go new file mode 100644 index 0000000..9d668f4 --- /dev/null +++ b/responses/uploadFiles.go @@ -0,0 +1,13 @@ +package responses + +type UploadPhotoFile struct { + Server int `json:"server,omitempty"` + PhotosList string `json:"photos_list,omitempty"` + Photo string `json:"photo,omitempty"` + AlbumID int `json:"aid,omitempty"` + Hash string `json:"hash,omitempty"` +} + +type UploadDocumentFile struct { + File string `json:"file,omitempty"` +} diff --git a/responses/uploadMessagesServer.go b/responses/uploadMessagesServer.go new file mode 100644 index 0000000..7e8b4c8 --- /dev/null +++ b/responses/uploadMessagesServer.go @@ -0,0 +1,21 @@ +package responses + +type UploadMessagesPhotoServerReply struct { + ErrorInterface + Response UploadMessagesPhotoServer `json:"response,omitempty"` +} + +type UploadMessagesPhotoServer struct { + AlbumID int `json:"album_id,omitempty"` + UserID int `json:"user_id,omitempty"` + UploadURL string `json:"upload_url,omitempty"` +} + +type UploadMessagesDocumentServerReply struct { + ErrorInterface + Response UploadMessagesDocumentServer `json:"response,omitempty"` +} + +type UploadMessagesDocumentServer struct { + UploadURL string `json:"upload_url,omitempty"` +} diff --git a/responses/users.go b/responses/users.go new file mode 100644 index 0000000..255a675 --- /dev/null +++ b/responses/users.go @@ -0,0 +1,363 @@ +package responses + +type UsersReply struct { + ErrorInterface + Response []User `json:"response,omitempty"` +} + +type User struct { + ID int `json:"id,omitempty"` + Name string `json:"first_name,omitempty"` + Surname string `json:"last_name,omitempty"` + Deactivated string `json:"deactivated,omitempty"` + IsClosed bool `json:"is_closed"` + CanAccessClosed bool `json:"can_access_closed"` + About string `json:"about,omitempty"` + Activities string `json:"activities,omitempty"` + Birthdate string `json:"bdate,omitempty"` + Blacklisted int `json:"blacklisted,omitempty"` + BlacklistedByMe int `json:"blacklisted_by_me,omitempty"` + Books string `json:"books,omitempty"` + CanPost int `json:"can_post,omitempty"` + CanSeeAllPosts int `json:"can_see_all_posts,omitempty"` + CanSeeAudio int `json:"can_see_audio,omitempty"` + CanSendFriendRequest int `json:"can_send_friend_request,omitempty"` + CanWriteMessage int `json:"can_write_private_message,omitempty"` + Career []UserCareer `json:"career,omitempty"` + City City `json:"city,omitempty"` + MutualFriends int `json:"common_count,omitempty"` + Connections any `json:"connections,omitempty"` + Contacts UserContacts `json:"contacts,omitempty"` + Counters UserCounters `json:"counters,omitempty"` + Country Country `json:"country,omitempty"` + CropPhoto CropPhoto `json:"crop_photo,omitempty"` + Domain string `json:"domain,omitempty"` + Education UserEducation `json:"education,omitempty"` + Exports any `json:"exports,omitempty"` + NameNominative string `json:"first_name_nom,omitempty"` + NameGenitive string `json:"first_name_gen,omitempty"` + NameDative string `json:"first_name_dat,omitempty"` + NameAccusative string `json:"first_name_acc,omitempty"` + NameInstrumental string `json:"first_name_ins,omitempty"` + NameAblative string `json:"first_name_abl,omitempty"` + FollowersCount int `json:"followers_count,omitempty"` + Games string `json:"games,omitempty"` + HasMobile int `json:"has_mobile,omitempty"` + HasPhoto int `json:"has_photo,omitempty"` + HomeTown string `json:"home_town,omitempty"` + Interests string `json:"interests,omitempty"` + IsFavorite int `json:"is_favorite,omitempty"` + IsFriend int `json:"is_friend,omitempty"` + IsHiddenFromFeed int `json:"is_hidden_from_feed,omitempty"` + IsNoIndex int `json:"is_no_index,omitempty"` + SurnameNominative string `json:"last_name_nom,omitempty"` + SurnameGenitive string `json:"last_name_gen,omitempty"` + SurnameDative string `json:"last_name_dat,omitempty"` + SurnameAccusative string `json:"last_name_acc,omitempty"` + SurnameInstrumental string `json:"last_name_ins,omitempty"` + SurnameAblative string `json:"last_name_abl,omitempty"` + LastSeen UserLastSeen `json:"last_seen,omitempty"` + Lists []int `json:"lists,omitempty"` + MaidenName string `json:"maiden_name,omitempty"` + Military UserMilitary `json:"military,omitempty"` + Movies string `json:"movies,omitempty"` + Music string `json:"music,omitempty"` + Nickname string `json:"nickname,omitempty"` + Occupation UserOccupation `json:"occupation,omitempty"` + Online int `json:"online,omitempty"` + OnlineMobile int `json:"online_mobile,omitempty"` + OnlineApplication int `json:"online_app,omitempty"` + OnlineInfo OnlineInfo `json:"online_info,omitempty"` + Personal UserPersonal `json:"personal,omitempty"` + Photo50 string `json:"photo_50,omitempty"` + Photo100 string `json:"photo_100,omitempty"` + Photo200Original string `json:"photo_200_orig,omitempty"` + Photo200 string `json:"photo_200,omitempty"` + Photo400Original string `json:"photo_400_orig,omitempty"` + PhotoID string `json:"photo_id,omitempty"` + PhotoMax string `json:"photo_max,omitempty"` + PhotoMaxOriginal string `json:"photo_max_orig,omitempty"` + Cover Cover `json:"cover"` + Quotes string `json:"quotes,omitempty"` + Relatives []UserRelative `json:"relatives,omitempty"` + Relation int `json:"relation,omitempty"` + Schools []UserSchool `json:"schools,omitempty"` + ScreenName string `json:"screen_name,omitempty"` + Gender int `json:"sex,omitempty"` + Site string `json:"site,omitempty"` + Status string `json:"status,omitempty"` + Timezone int `json:"timezone,omitempty"` + Trending int `json:"trending,omitempty"` + TV string `json:"tv,omitempty"` + Universities []UserUniversity `json:"universities,omitempty"` + Verified int `json:"verified,omitempty"` + WallDefault string `json:"wall_default,omitempty"` + + // without documentation + TrackCode string `json:"track_code,omitempty"` + WallComments int `json:"wall_comments,omitempty"` + MobilePhone string `json:"mobile_phone,omitempty"` + HomePhone string `json:"home_phone,omitempty"` + FriendStatus int `json:"friend_status,omitempty"` +} + +type UserCareer struct { + GroupID int `json:"group_id,omitempty"` + Company string `json:"company,omitempty"` + CountryID int `json:"country_id,omitempty"` + CityID int `json:"city_id,omitempty"` + CityName string `json:"city_name,omitempty"` + From int `json:"from,omitempty"` + Until int `json:"until,omitempty"` + Position string `json:"position,omitempty"` +} + +type UserContacts struct { + MobilePhone string `json:"mobile_phone,omitempty"` + HomePhone string `json:"home_phone,omitempty"` +} + +type UserCounters struct { + Albums int `json:"albums,omitempty"` + Videos int `json:"videos,omitempty"` + Audios int `json:"audios,omitempty"` + Photos int `json:"photos,omitempty"` + Notes int `json:"notes,omitempty"` + Friends int `json:"friends,omitempty"` + Gifts int `json:"gifts,omitempty"` + Groups int `json:"groups,omitempty"` + OnlineFriends int `json:"online_friends,omitempty"` + MutualFriends int `json:"mutual_friends,omitempty"` + UserVideos int `json:"user_videos,omitempty"` + UserPhotos int `json:"user_photos,omitempty"` + Followers int `json:"followers,omitempty"` + Pages int `json:"pages,omitempty"` + Subscriptions int `json:"subscriptions,omitempty"` +} + +type UserEducation struct { + University int `json:"university,omitempty"` + UniversityName string `json:"university_name,omitempty"` + Faculty int `json:"faculty,omitempty"` + FacultyName string `json:"faculty_name,omitempty"` + Graduation int `json:"graduation,omitempty"` +} + +type UserLastSeen struct { + Platform int `json:"platform,omitempty"` + Time int `json:"time,omitempty"` +} + +type UserMilitary struct { + Unit string `json:"unit,omitempty"` + UnitID int `json:"unit_id,omitempty"` + CountryID int `json:"country_id,omitempty"` + From int `json:"from,omitempty"` + Until int `json:"until,omitempty"` +} + +type UserOccupation struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` +} + +type UserPersonal struct { + Political int `json:"political,omitempty"` + Languages []string `json:"langs,omitempty"` + Religion string `json:"religion,omitempty"` + InspiredBy string `json:"inspired_by,omitempty"` + PeopleMain int `json:"people_main,omitempty"` + LifeMain int `json:"life_main,omitempty"` + Smoking int `json:"smoking,omitempty"` + Alcohol int `json:"alcohol,omitempty"` +} + +type UserRelative struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` +} + +type UserSchool struct { + ID string `json:"id,omitempty"` + CountryID int `json:"country,omitempty"` + CityID int `json:"city,omitempty"` + Name string `json:"name,omitempty"` + YearFrom int `json:"year_from,omitempty"` + YearTo int `json:"year_to,omitempty"` + YearGraduated int `json:"year_graduated,omitempty"` + Class string `json:"class,omitempty"` + Speciality string `json:"speciality,omitempty"` + Type int `json:"type,omitempty"` + TypeString string `json:"type_str,omitempty"` +} + +type UserUniversity struct { + ID int `json:"id,omitempty"` + CountryID int `json:"country,omitempty"` + CityID int `json:"city,omitempty"` + Name string `json:"name,omitempty"` + FacultyID int `json:"faculty,omitempty"` + FacultyName string `json:"faculty_name,omitempty"` + ChairID int `json:"chair,omitempty"` + ChairName string `json:"chair_name,omitempty"` + Graduation int `json:"graduation,omitempty"` + EducationForm string `json:"education_form,omitempty"` + EducationStatus string `json:"education_status,omitempty"` +} + +type OnlineInfo struct { + Visible bool `json:"visible,omitempty"` + LastSeen int `json:"last_seen,omitempty"` + IsOnline bool `json:"is_online,omitempty"` + ApplicationID int `json:"app_id,omitempty"` + IsMobile bool `json:"is_mobile,omitempty"` +} + +type FollowersReply struct { + ErrorInterface + Response Followers `json:"response,omitempty"` +} + +type Followers struct { + FriendsCount int `json:"friends_count,omitempty"` + Items []User `json:"items,omitempty"` +} + +type SubscriptionsReply struct { + ErrorInterface + Response Subscriptions `json:"response,omitempty"` +} + +type Subscriptions struct { + Items []Subscription `json:"items,omitempty"` +} + +type Subscription struct { + ErrorInterface + ID int `json:"id,omitempty"` + TrackCode string `json:"track_code,omitempty"` + Name string `json:"first_name,omitempty"` + Surname string `json:"last_name,omitempty"` + Deactivated string `json:"deactivated,omitempty"` + IsClosed bool `json:"is_closed"` + CanAccessClosed bool `json:"can_access_closed"` + About string `json:"about,omitempty"` + Activities string `json:"activities,omitempty"` + Birthdate string `json:"bdate,omitempty"` + Blacklisted int `json:"blacklisted,omitempty"` + BlacklistedByMe int `json:"blacklisted_by_me,omitempty"` + Books string `json:"books,omitempty"` + CanPost int `json:"can_post,omitempty"` + CanSeeAllPosts int `json:"can_see_all_posts,omitempty"` + CanSeeAudio int `json:"can_see_audio,omitempty"` + CanSendFriendRequest int `json:"can_send_friend_request,omitempty"` + CanWriteMessage int `json:"can_write_private_message,omitempty"` + Career []UserCareer `json:"career,omitempty"` + City City `json:"city,omitempty"` + MutualFriends int `json:"common_count,omitempty"` + Connections any `json:"connections,omitempty"` + Contacts UserContacts `json:"contacts,omitempty"` + Counters UserCounters `json:"counters,omitempty"` + Country Country `json:"country,omitempty"` + CropPhoto CropPhoto `json:"crop_photo,omitempty"` + Domain string `json:"domain,omitempty"` + Education UserEducation `json:"education,omitempty"` + Exports any `json:"exports,omitempty"` + NameNominative string `json:"first_name_nom,omitempty"` + NameGenitive string `json:"first_name_gen,omitempty"` + NameDative string `json:"first_name_dat,omitempty"` + NameAccusative string `json:"first_name_acc,omitempty"` + NameInstrumental string `json:"first_name_ins,omitempty"` + NameAblative string `json:"first_name_abl,omitempty"` + FollowersCount int `json:"followers_count,omitempty"` + Games string `json:"games,omitempty"` + HasMobile int `json:"has_mobile,omitempty"` + HasPhoto int `json:"has_photo,omitempty"` + HomeTown string `json:"home_town,omitempty"` + Interests string `json:"interests,omitempty"` + IsFavorite int `json:"is_favorite,omitempty"` + IsFriend int `json:"is_friend,omitempty"` + IsHiddenFromFeed int `json:"is_hidden_from_feed,omitempty"` + IsNoIndex int `json:"is_no_index,omitempty"` + SurnameNominative string `json:"last_name_nom,omitempty"` + SurnameGenitive string `json:"last_name_gen,omitempty"` + SurnameDative string `json:"last_name_dat,omitempty"` + SurnameAccusative string `json:"last_name_acc,omitempty"` + SurnameInstrumental string `json:"last_name_ins,omitempty"` + SurnameAblative string `json:"last_name_abl,omitempty"` + LastSeen UserLastSeen `json:"last_seen,omitempty"` + Lists string `json:"lists,omitempty"` + MaidenName string `json:"maiden_name,omitempty"` + Military UserMilitary `json:"military,omitempty"` + Movies string `json:"movies,omitempty"` + Music string `json:"music,omitempty"` + Nickname string `json:"nickname,omitempty"` + Occupation UserOccupation `json:"occupation,omitempty"` + Online int `json:"online,omitempty"` + Personal UserPersonal `json:"personal,omitempty"` + Photo50 string `json:"photo_50,omitempty"` + Photo100 string `json:"photo_100,omitempty"` + Photo200Original string `json:"photo_200_orig,omitempty"` + Photo200 string `json:"photo_200,omitempty"` + Photo400Original string `json:"photo_400_orig,omitempty"` + PhotoID string `json:"photo_id,omitempty"` + PhotoMax string `json:"photo_max,omitempty"` + PhotoMaxOriginal string `json:"photo_max_orig,omitempty"` + Quotes string `json:"quotes,omitempty"` + Relatives []UserRelative `json:"relatives,omitempty"` + Relation int `json:"relation,omitempty"` + Schools []UserSchool `json:"schools,omitempty"` + ScreenName string `json:"screen_name,omitempty"` + Gender int `json:"sex,omitempty"` + Site string `json:"site,omitempty"` + Status string `json:"status,omitempty"` + Timezone int `json:"timezone,omitempty"` + Trending int `json:"trending,omitempty"` + TV string `json:"tv,omitempty"` + Universities []UserUniversity `json:"universities,omitempty"` + Verified int `json:"verified,omitempty"` + WallDefault string `json:"wall_default,omitempty"` + IsAdmin int `json:"is_admin,omitempty"` + AdminLevel int `json:"admin_level,omitempty"` + IsMember int `json:"is_member,omitempty"` + IsAdvertiser int `json:"is_advertiser,omitempty"` + InvitedBy int `json:"invited_by,omitempty"` + Type string `json:"type,omitempty"` + Activity string `json:"activity,omitempty"` + Addresses Addresses `json:"addresses,omitempty"` + AgeLimits int `json:"age_limits,omitempty"` + BanInfo BanInfo `json:"ban_info,omitempty"` + CanCreateTopic int `json:"can_create_topic,omitempty"` + CanMessage int `json:"can_message,omitempty"` + CanSuggest int `json:"can_suggest,omitempty"` + CanUploadDoc int `json:"can_upload_doc,omitempty"` + CanUploadStory int `json:"can_upload_story,omitempty"` + CanUploadVideo int `json:"can_upload_video,omitempty"` + Cover Cover `json:"cover,omitempty"` + Description string `json:"description,omitempty"` + PinnedPost int `json:"fixed_post,omitempty"` + IsMessagesBlocked int `json:"is_messages_blocked,omitempty"` + Links []Link `json:"links,omitempty"` + MainAlbumID int `json:"main_album_id,omitempty"` + MainSection int `json:"main_section,omitempty"` + Market Market `json:"market,omitempty"` + MemberStatus int `json:"member_status,omitempty"` + MembersCount int `json:"members_count,omitempty"` + Place Place `json:"place,omitempty"` + PublicDateLabel string `json:"public_date_label,omitempty"` + StartDate any `json:"start_date,omitempty"` + FinishDate string `json:"finish_date,omitempty"` + Wall int `json:"wall,omitempty"` + WikiPage string `json:"wiki_page,omitempty"` +} + +type SearchUserReply struct { + ErrorInterface + Response SearchUser `json:"response,omitempty"` +} + +type SearchUser struct { + Items []User `json:"items,omitempty"` +} diff --git a/responses/widgets.go b/responses/widgets.go new file mode 100644 index 0000000..763eae8 --- /dev/null +++ b/responses/widgets.go @@ -0,0 +1,6 @@ +package responses + +type UpdateWidgetsReply struct { + ErrorInterface + Response int `json:"response,omitempty"` +} diff --git a/samples/callback-bot/main.go b/samples/callback-bot/main.go new file mode 100644 index 0000000..564c4ee --- /dev/null +++ b/samples/callback-bot/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "log" + "os" + + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/callback" + "github.com/aejoy/vkgo/samples/scenes" + "github.com/aejoy/vkgo/scene" + fiber "github.com/gofiber/fiber/v2" +) + +func main() { + bot, err := api.New(os.Getenv("TOKEN")) + if err != nil { + panic(err) + } + + messageScene := scene.Message(scenes.NewMessageScene) + + cb := callback.New(messageScene) + cb.Add(bot) + + app := fiber.New() + app.Post("/vk/:confirmation", cb.Router.Fiber) + log.Fatalln(app.Listen(":3200")) +} diff --git a/samples/community-bot/main.go b/samples/community-bot/main.go new file mode 100644 index 0000000..2c2d478 --- /dev/null +++ b/samples/community-bot/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "log" + "os" + + "github.com/aejoy/vkgo/longpoll" + "github.com/aejoy/vkgo/samples/scenes" + "github.com/aejoy/vkgo/scene" + + "github.com/aejoy/vkgo/api" +) + +func main() { + bot, err := api.New(os.Getenv("TOKEN")) + if err != nil { + panic(err) + } + + log.Fatalln(longpoll.Start(bot, scene.Message(scenes.NewMessageScene))) +} diff --git a/samples/longpoll-bot/main.go b/samples/longpoll-bot/main.go new file mode 100644 index 0000000..8cdc6c1 --- /dev/null +++ b/samples/longpoll-bot/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "log" + "os" + + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/longpoll" + "github.com/aejoy/vkgo/samples/scenes" + "github.com/aejoy/vkgo/scene" +) + +func main() { + bot, err := api.New(os.Getenv("USER_TOKEN")) + if err != nil { + panic(err) + } + + log.Fatalln(longpoll.Start(bot, scene.Message(scenes.NewMessageScene))) +} diff --git a/samples/multi-bot/main.go b/samples/multi-bot/main.go new file mode 100644 index 0000000..27eac81 --- /dev/null +++ b/samples/multi-bot/main.go @@ -0,0 +1,37 @@ +package main + +import ( + "os" + + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/multibot" + "github.com/aejoy/vkgo/samples/scenes" + "github.com/aejoy/vkgo/scene" + "go.uber.org/zap" +) + +func main() { + diamond, err := api.New(os.Getenv("DIAMOND_TOKEN")) + if err != nil { + panic(err) + } + + sapphire, err := api.New(os.Getenv("SAPPHIRE_TOKEN")) + if err != nil { + panic(err) + } + + logger, err := zap.NewProduction() + if err != nil { + panic(err) + } + + diamond.Logger = logger + sapphire.Logger = logger + + bots := []*api.API{diamond, sapphire} + + messageScene := scene.Message(scenes.NewMessageScene) + + multibot.New(bots, messageScene, logger).Start() +} diff --git a/samples/scenes/scenes.go b/samples/scenes/scenes.go new file mode 100644 index 0000000..2db9a3b --- /dev/null +++ b/samples/scenes/scenes.go @@ -0,0 +1,71 @@ +package scenes + +import ( + "fmt" + "time" + + "github.com/aejoy/vkgo/utils" + + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/types" + "github.com/aejoy/vkgo/update" +) + +func NewMessageScene(bot *api.API, message update.Message) { + switch message.Text { + case ":пинг": + text, startTime := "✦ Понг!", time.Now() + + sent, err := bot.SendMessage(message.ChatID, text) + if err != nil { + panic(err) + } + + if _, err := bot.EditMessage(sent.ChatID, sent.ChatMessageID, + fmt.Sprintf("%s (%v)", + text, + time.Since(startTime), + ), + ); err != nil { + panic(err) + } + case ":upload": + fileByte, err := utils.GetFileFromURL("https://4kwallpapers.com/images/walls/thumbs_3t/18949.jpg") + if err != nil { + panic(err) + } + + photo, err := bot.UploadMessagesPhoto(message.ChatID, "wallpaper-4k.png", fileByte) + if err != nil { + panic(err) + } + + if _, err := bot.SendMessage(types.SendMessage{ + ChatID: message.ChatID, + Attachment: fmt.Sprintf("photo%d_%d_%s", photo.OwnerID, photo.ID, photo.AccessKey), + }); err != nil { + panic(err) + } + case ":album upload": + fileByte, err := utils.GetFileFromURL("https://i.pinimg.com/736x/4d/1d/b0/4d1db0811c9c0f48cf7ed11c6ab00a7b.jpg") + if err != nil { + panic(err) + } + + clubAlbumID, groupID := 301684048, 226420674 + + photos, err := bot.UploadAlbumPhotos(clubAlbumID, []types.UploadFile{ + {FieldName: "file1", FileName: "meme.png", Bytes: fileByte}, + }, groupID) + if err != nil { + panic(err) + } + + if _, err := bot.SendMessage(types.SendMessage{ + ChatID: message.ChatID, + Attachment: fmt.Sprintf("photo%d_%d", photos[0].OwnerID, photos[0].ID), + }); err != nil { + panic(err) + } + } +} diff --git a/scene/methods.go b/scene/methods.go new file mode 100644 index 0000000..e77dfc7 --- /dev/null +++ b/scene/methods.go @@ -0,0 +1,517 @@ +package scene + +// Messages + +func Message(msgFunc MessageFunc) *Scenes { + return NewScene().Message(msgFunc) +} + +func OnMessage(msgFunc MessageFunc) *Scenes { + return NewScene().Message(msgFunc) +} + +func (scenes *Scenes) Message(msgFunc MessageFunc) *Scenes { + scenes.MessageFunc = msgFunc + return scenes +} + +func Callback(cbFunc CallbackFunc) *Scenes { + return NewScene().Callback(cbFunc) +} + +func (scenes *Scenes) Callback(cbFunc CallbackFunc) *Scenes { + scenes.CallbackFunc = cbFunc + return scenes +} + +func ReplyMessage(replMsgFunc ReplyMessageFunc) *Scenes { + return NewScene().ReplyMessage(replMsgFunc) +} + +func (scenes *Scenes) ReplyMessage(replMsgFunc ReplyMessageFunc) *Scenes { + scenes.ReplyMessageFunc = replMsgFunc + return scenes +} + +func EditMessage(edMsgFunc EditMessageFunc) *Scenes { + return NewScene().EditMessage(edMsgFunc) +} + +func (scenes *Scenes) EditMessage(edMsgFunc EditMessageFunc) *Scenes { + scenes.EditMessageFunc = edMsgFunc + return scenes +} + +func EnableMessage(enbMsgFunc EnableMessageFunc) *Scenes { + return NewScene().EnableMessage(enbMsgFunc) +} + +func (scenes *Scenes) EnableMessage(enbMsgFunc EnableMessageFunc) *Scenes { + scenes.EnableMessageFunc = enbMsgFunc + return scenes +} + +func DisableMessage(disMsgFunc DisableMessageFunc) *Scenes { + return NewScene().DisableMessage(disMsgFunc) +} + +func (scenes *Scenes) DisableMessage(disMsgFunc DisableMessageFunc) *Scenes { + scenes.DisableMessageFunc = disMsgFunc + return scenes +} + +func TypingMessage(typFunc TypingMessageFunc) *Scenes { + return NewScene().TypingMessage(typFunc) +} + +func (scenes *Scenes) TypingMessage(typFunc TypingMessageFunc) *Scenes { + scenes.TypingMessageFunc = typFunc + return scenes +} + +// Photos + +func Photo(photoFunc PhotoFunc) *Scenes { + return NewScene().Photo(photoFunc) +} + +func (scenes *Scenes) Photo(photoFunc PhotoFunc) *Scenes { + scenes.PhotoFunc = photoFunc + return scenes +} + +func PhotoComment(photoComFunc PhotoCommentFunc) *Scenes { + return NewScene().PhotoComment(photoComFunc) +} + +func (scenes *Scenes) PhotoComment(photoComFunc PhotoCommentFunc) *Scenes { + scenes.PhotoCommentFunc = photoComFunc + return scenes +} + +func EditPhotoComment(edPhotoFunc EditPhotoCommentFunc) *Scenes { + return NewScene().EditPhotoComment(edPhotoFunc) +} + +func (scenes *Scenes) EditPhotoComment(edPhotoFunc EditPhotoCommentFunc) *Scenes { + scenes.EditPhotoCommentFunc = edPhotoFunc + return scenes +} + +func RestorePhotoComment(restPhotoComFunc RestorePhotoCommentFunc) *Scenes { + return NewScene().RestorePhotoComment(restPhotoComFunc) +} + +func (scenes *Scenes) RestorePhotoComment(restPhotoComFunc RestorePhotoCommentFunc) *Scenes { + scenes.RestorePhotoCommentFunc = restPhotoComFunc + return scenes +} + +func DeletePhotoComment(delPhotoComFunc DeletePhotoCommentFunc) *Scenes { + return NewScene().DeletePhotoComment(delPhotoComFunc) +} + +func (scenes *Scenes) DeletePhotoComment(delPhotoComFunc DeletePhotoCommentFunc) *Scenes { + scenes.DeletePhotoCommentFunc = delPhotoComFunc + return scenes +} + +// Sounds + +func Audio(audFunc NewAudioFunc) *Scenes { + return NewScene().Audio(audFunc) +} + +func (scenes *Scenes) Audio(audFunc NewAudioFunc) *Scenes { + scenes.NewAudioFunc = audFunc + return scenes +} + +// Videos + +func Video(vidFunc NewVideoFunc) *Scenes { + return NewScene().Video(vidFunc) +} + +func (scenes *Scenes) Video(vidFunc NewVideoFunc) *Scenes { + scenes.NewVideoFunc = vidFunc + return scenes +} + +func VideoComment(vidComFunc VideoCommentFunc) *Scenes { + return NewScene().VideoComment(vidComFunc) +} + +func (scenes *Scenes) VideoComment(vidComFunc VideoCommentFunc) *Scenes { + scenes.VideoCommentFunc = vidComFunc + return scenes +} + +func EditVideoComment(edVidComFunc EditVideoCommentFunc) *Scenes { + return NewScene().EditVideoComment(edVidComFunc) +} + +func (scenes *Scenes) EditVideoComment(edVidComFunc EditVideoCommentFunc) *Scenes { + scenes.EditVideoCommentFunc = edVidComFunc + return scenes +} + +func RestoreVideoComment(restVidComFunc RestoreVideoCommentFunc) *Scenes { + return NewScene().RestoreVideoComment(restVidComFunc) +} + +func (scenes *Scenes) RestoreVideoComment(restVidComFunc RestoreVideoCommentFunc) *Scenes { + scenes.RestoreVideoCommentFunc = restVidComFunc + return scenes +} + +func DeleteVideoComment(delVidComFunc DeleteVideoCommentFunc) *Scenes { + return NewScene().DeleteVideoComment(delVidComFunc) +} + +func (scenes *Scenes) DeleteVideoComment(delVidComFunc DeleteVideoCommentFunc) *Scenes { + scenes.DeleteVideoCommentFunc = delVidComFunc + return scenes +} + +// Posts + +func Post(postFunc PostFunc) *Scenes { + return NewScene().Post(postFunc) +} + +func (scenes *Scenes) Post(postFunc PostFunc) *Scenes { + scenes.PostFunc = postFunc + return scenes +} + +func Repost(postFunc RepostFunc) *Scenes { + return NewScene().Repost(postFunc) +} + +func (scenes *Scenes) Repost(repost RepostFunc) *Scenes { + scenes.RepostFunc = repost + return scenes +} + +func PostComment(postComFunc PostCommentFunc) *Scenes { + return NewScene().PostComment(postComFunc) +} + +func (scenes *Scenes) PostComment(postComFunc PostCommentFunc) *Scenes { + scenes.PostCommentFunc = postComFunc + return scenes +} + +func EditPostComment(edPostComFunc EditPostCommentFunc) *Scenes { + return NewScene().EditPostComment(edPostComFunc) +} + +func (scenes *Scenes) EditPostComment(editPostComment EditPostCommentFunc) *Scenes { + scenes.EditPostCommentFunc = editPostComment + return scenes +} + +func RestorePostComment(restPostFunc RestorePostCommentFunc) *Scenes { + return NewScene().RestorePostComment(restPostFunc) +} + +func (scenes *Scenes) RestorePostComment(restPostFunc RestorePostCommentFunc) *Scenes { + scenes.RestorePostCommentFunc = restPostFunc + return scenes +} + +func DeletePostComment(delPostComFunc DeletePostCommentFunc) *Scenes { + return NewScene().DeletePostComment(delPostComFunc) +} + +func (scenes *Scenes) DeletePostComment(delPostComFunc DeletePostCommentFunc) *Scenes { + scenes.DeletePostCommentFunc = delPostComFunc + return scenes +} + +// Likes + +func Like(likeFunc LikeFunc) *Scenes { + return NewScene().Like(likeFunc) +} + +func (scenes *Scenes) Like(likeFunc LikeFunc) *Scenes { + scenes.LikeFunc = likeFunc + return scenes +} + +func Unlike(unlikeFunc UnlikeFunc) *Scenes { + return NewScene().Unlike(unlikeFunc) +} + +func (scenes *Scenes) Unlike(unlikeFunc UnlikeFunc) *Scenes { + scenes.UnlikeFunc = unlikeFunc + return scenes +} + +// Board Comments + +func BoardComment(boardComFunc BoardCommentFunc) *Scenes { + return NewScene().BoardComment(boardComFunc) +} + +func (scenes *Scenes) BoardComment(boardComFunc BoardCommentFunc) *Scenes { + scenes.BoardCommentFunc = boardComFunc + return scenes +} + +func EditBoardComment(edBoardComFunc EditBoardCommentFunc) *Scenes { + return NewScene().EditBoardComment(edBoardComFunc) +} + +func (scenes *Scenes) EditBoardComment(edBoardComFunc EditBoardCommentFunc) *Scenes { + scenes.EditBoardCommentFunc = edBoardComFunc + return scenes +} + +func RestoreBoardComment(restBoardComFunc RestoreBoardCommentFunc) *Scenes { + return NewScene().RestoreBoardComment(restBoardComFunc) +} + +func (scenes *Scenes) RestoreBoardComment(restBoardComFunc RestoreBoardCommentFunc) *Scenes { + scenes.RestoreBoardCommentFunc = restBoardComFunc + return scenes +} + +func DeleteBoardComment(delBoardComFunc DeleteBoardCommentFunc) *Scenes { + return NewScene().DeleteBoardComment(delBoardComFunc) +} + +func (scenes *Scenes) DeleteBoardComment(delBoardComFunc DeleteBoardCommentFunc) *Scenes { + scenes.DeleteBoardCommentFunc = delBoardComFunc + return scenes +} + +// Market Comments + +func MarketComment(marketComFunc MarketCommentFunc) *Scenes { + return NewScene().MarketComment(marketComFunc) +} + +func (scenes *Scenes) MarketComment(marketComFunc MarketCommentFunc) *Scenes { + scenes.MarketCommentFunc = marketComFunc + return scenes +} + +func EditMarketComment(edMarketComFunc EditMarketCommentFunc) *Scenes { + return NewScene().EditMarketComment(edMarketComFunc) +} + +func (scenes *Scenes) EditMarketComment(edMarketComFunc EditMarketCommentFunc) *Scenes { + scenes.EditMarketCommentFunc = edMarketComFunc + return scenes +} + +func RestoreMarketComment(restMarketComFunc RestoreMarketCommentFunc) *Scenes { + return NewScene().RestoreMarketComment(restMarketComFunc) +} + +func (scenes *Scenes) RestoreMarketComment(restMarketComFunc RestoreMarketCommentFunc) *Scenes { + scenes.RestoreMarketCommentFunc = restMarketComFunc + return scenes +} + +func DeleteMarketComment(delMarketComFunc DeleteMarketCommentFunc) *Scenes { + return NewScene().DeleteMarketComment(delMarketComFunc) +} + +func (scenes *Scenes) DeleteMarketComment(delMarketComFunc DeleteMarketCommentFunc) *Scenes { + scenes.DeleteMarketCommentFunc = delMarketComFunc + return scenes +} + +// Orders + +func OrderMarket(orderMarketFunc OrderMarketFunc) *Scenes { + return NewScene().OrderMarket(orderMarketFunc) +} + +func (scenes *Scenes) OrderMarket(orderMarketFunc OrderMarketFunc) *Scenes { + scenes.OrderMarketFunc = orderMarketFunc + return scenes +} + +func EditOrderMarket(edOrderMarketFunc EditOrderMarketFunc) *Scenes { + return NewScene().EditOrderMarket(edOrderMarketFunc) +} + +func (scenes *Scenes) EditOrderMarket(edOrderMarketFunc EditOrderMarketFunc) *Scenes { + scenes.EditOrderMarketFunc = edOrderMarketFunc + return scenes +} + +func EditOrder(edOrderMarketFunc EditOrderMarketFunc) *Scenes { + return NewScene().EditOrder(edOrderMarketFunc) +} + +func (scenes *Scenes) EditOrder(edOrderMarketFunc EditOrderMarketFunc) *Scenes { + scenes.EditOrderMarketFunc = edOrderMarketFunc + return scenes +} + +// Community + +func JoinGroup(jGroupFunc JoinGroupFunc) *Scenes { + return NewScene().JoinGroup(jGroupFunc) +} + +func (scenes *Scenes) JoinGroup(jGroupFunc JoinGroupFunc) *Scenes { + scenes.JoinGroupFunc = jGroupFunc + return scenes +} + +func LeaveGroup(lGroupFunc LeaveGroupFunc) *Scenes { + return NewScene().LeaveGroup(lGroupFunc) +} + +func (scenes *Scenes) LeaveGroup(lGroupFunc LeaveGroupFunc) *Scenes { + scenes.LeaveGroupFunc = lGroupFunc + return scenes +} + +func BlockUser(blockUserFunc BlockUserFunc) *Scenes { + return NewScene().BlockUser(blockUserFunc) +} + +func (scenes *Scenes) BlockUser(blockUserFunc BlockUserFunc) *Scenes { + scenes.BlockUserFunc = blockUserFunc + return scenes +} + +func UnblockUser(unblockUserFunc UnblockUserFunc) *Scenes { + return NewScene().UnblockUser(unblockUserFunc) +} + +func (scenes *Scenes) UnblockUser(unblockUserFunc UnblockUserFunc) *Scenes { + scenes.UnblockUserFunc = unblockUserFunc + return scenes +} + +// Others + +func Vote(voteFunc VoteFunc) *Scenes { + return NewScene().Vote(voteFunc) +} + +func (scenes *Scenes) Vote(voteFunc VoteFunc) *Scenes { + scenes.VoteFunc = voteFunc + return scenes +} + +func EditOwners(edPwnFunc EditOwnersFunc) *Scenes { + return NewScene().EditOwners(edPwnFunc) +} + +func (scenes *Scenes) EditOwners(edPwnFunc EditOwnersFunc) *Scenes { + scenes.EditOwnersFunc = edPwnFunc + return scenes +} + +func ControlGroup(ctrlGroupFunc ControlGroupFunc) *Scenes { + return NewScene().ControlGroup(ctrlGroupFunc) +} + +func (scenes *Scenes) ControlGroup(ctrlGroupFunc ControlGroupFunc) *Scenes { + scenes.ControlGroupFunc = ctrlGroupFunc + return scenes +} + +func ChangeGroupPhoto(chGroupPhotoFunc ChangeGroupPhotoFunc) *Scenes { + return NewScene().ChangeGroupPhoto(chGroupPhotoFunc) +} + +func (scenes *Scenes) ChangeGroupPhoto(chGroupPhotoFunc ChangeGroupPhotoFunc) *Scenes { + scenes.ChangeGroupPhotoFunc = chGroupPhotoFunc + return scenes +} + +func VKPayTransaction(vkPayTransFunc VKPayTransactionFunc) *Scenes { + return NewScene().VKPayTransaction(vkPayTransFunc) +} + +func (scenes *Scenes) VKPayTransaction(vkPayTransFunc VKPayTransactionFunc) *Scenes { + scenes.VKPayTransactionFunc = vkPayTransFunc + return scenes +} + +func AppNotification(appNotifyFunc AppNotificationFunc) *Scenes { + return NewScene().ApplicationNotification(appNotifyFunc) +} + +func ApplicationNotification(appNotifyFunc AppNotificationFunc) *Scenes { + return NewScene().ApplicationNotification(appNotifyFunc) +} + +func (scenes *Scenes) ApplicationNotification(appNotifyFunc AppNotificationFunc) *Scenes { + scenes.AppNotificationFunc = appNotifyFunc + return scenes +} + +func Donate(donFunc DonateFunc) *Scenes { + return NewScene().Donate(donFunc) +} + +func (scenes *Scenes) Donate(donFunc DonateFunc) *Scenes { + scenes.DonateFunc = donFunc + return scenes +} + +func ProlongedDonate(proDonFunc ProlongedDonateFunc) *Scenes { + return NewScene().ProlongedDonate(proDonFunc) +} + +func (scenes *Scenes) ProlongedDonate(proDonFunc ProlongedDonateFunc) *Scenes { + scenes.ProlongedDonateFunc = proDonFunc + return scenes +} + +func ExpiredDonate(expDonFunc ExpiredDonateFunc) *Scenes { + return NewScene().ExpiredDonate(expDonFunc) +} + +func (scenes *Scenes) ExpiredDonate(expDonFunc ExpiredDonateFunc) *Scenes { + scenes.ExpiredDonateFunc = expDonFunc + return scenes +} + +func CancelDonate(cancDonFunc CancelDonateFunc) *Scenes { + return NewScene().CancelDonate(cancDonFunc) +} + +func (scenes *Scenes) CancelDonate(cancDonFunc CancelDonateFunc) *Scenes { + scenes.CancelDonateFunc = cancDonFunc + return scenes +} + +func ChangeDonatePrice(chDonPriceFunc ChangeDonatePriceFunc) *Scenes { + return NewScene().ChangeDonatePrice(chDonPriceFunc) +} + +func (scenes *Scenes) ChangeDonatePrice(chDonPriceFunc ChangeDonatePriceFunc) *Scenes { + scenes.ChangeDonatePriceFunc = chDonPriceFunc + return scenes +} + +func WithdrawMoney(withdrawMoneyFunc WithdrawMoneyFunc) *Scenes { + return NewScene().WithdrawMoney(withdrawMoneyFunc) +} + +func (scenes *Scenes) WithdrawMoney(withdrawMoneyFunc WithdrawMoneyFunc) *Scenes { + scenes.WithdrawMoneyFunc = withdrawMoneyFunc + return scenes +} + +func WithdrawMoneyError(withdrawMoneyErrFunc WithdrawMoneyErrorFunc) *Scenes { + return NewScene().WithdrawMoneyError(withdrawMoneyErrFunc) +} + +func (scenes *Scenes) WithdrawMoneyError(withdrawMoneyErrFunc WithdrawMoneyErrorFunc) *Scenes { + scenes.WithdrawMoneyErrorFunc = withdrawMoneyErrFunc + return scenes +} diff --git a/scene/scene.go b/scene/scene.go new file mode 100644 index 0000000..678a569 --- /dev/null +++ b/scene/scene.go @@ -0,0 +1,146 @@ +package scene + +import ( + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/update" +) + +type Func func(*api.API, update.Update, Scenes) + +type Scenes struct { + MessageFunc MessageFunc + ReplyMessageFunc ReplyMessageFunc + EditMessageFunc EditMessageFunc + EnableMessageFunc EnableMessageFunc + DisableMessageFunc DisableMessageFunc + TypingMessageFunc TypingMessageFunc + CallbackFunc CallbackFunc + + PhotoFunc PhotoFunc + PhotoCommentFunc PhotoCommentFunc + EditPhotoCommentFunc EditPhotoCommentFunc + RestorePhotoCommentFunc RestorePhotoCommentFunc + DeletePhotoCommentFunc DeletePhotoCommentFunc + + NewAudioFunc NewAudioFunc + + NewVideoFunc NewVideoFunc + VideoCommentFunc VideoCommentFunc + EditVideoCommentFunc EditVideoCommentFunc + RestoreVideoCommentFunc RestoreVideoCommentFunc + DeleteVideoCommentFunc DeleteVideoCommentFunc + + PostFunc PostFunc + RepostFunc RepostFunc + PostCommentFunc PostCommentFunc + EditPostCommentFunc EditPostCommentFunc + RestorePostCommentFunc RestorePostCommentFunc + DeletePostCommentFunc DeletePostCommentFunc + + LikeFunc LikeFunc + UnlikeFunc UnlikeFunc + + BoardCommentFunc BoardCommentFunc + EditBoardCommentFunc EditBoardCommentFunc + RestoreBoardCommentFunc RestoreBoardCommentFunc + DeleteBoardCommentFunc DeleteBoardCommentFunc + + MarketCommentFunc MarketCommentFunc + EditMarketCommentFunc EditMarketCommentFunc + RestoreMarketCommentFunc RestoreMarketCommentFunc + DeleteMarketCommentFunc DeleteMarketCommentFunc + + OrderMarketFunc OrderMarketFunc + EditOrderMarketFunc EditOrderMarketFunc + + JoinGroupFunc JoinGroupFunc + LeaveGroupFunc LeaveGroupFunc + + BlockUserFunc BlockUserFunc + UnblockUserFunc UnblockUserFunc + + VoteFunc VoteFunc + EditOwnersFunc EditOwnersFunc + ControlGroupFunc ControlGroupFunc + ChangeGroupPhotoFunc ChangeGroupPhotoFunc + VKPayTransactionFunc VKPayTransactionFunc + AppNotificationFunc AppNotificationFunc + + DonateFunc DonateFunc + ProlongedDonateFunc ProlongedDonateFunc + ExpiredDonateFunc ExpiredDonateFunc + CancelDonateFunc CancelDonateFunc + ChangeDonatePriceFunc ChangeDonatePriceFunc + WithdrawMoneyFunc WithdrawMoneyFunc + WithdrawMoneyErrorFunc WithdrawMoneyErrorFunc +} + +type MessageFunc func(*api.API, update.Message) +type ReplyMessageFunc func(*api.API, update.Message) +type EditMessageFunc func(*api.API, update.Message) +type EnableMessageFunc func(*api.API, update.EnableMessage) +type DisableMessageFunc func(*api.API, update.DisableMessage) +type TypingMessageFunc func(*api.API, update.Typing) +type CallbackFunc func(*api.API, update.Callback) + +type PhotoFunc func(*api.API, update.Photo) +type PhotoCommentFunc func(*api.API, update.PhotoComment) +type EditPhotoCommentFunc PhotoCommentFunc +type RestorePhotoCommentFunc PhotoCommentFunc +type DeletePhotoCommentFunc PhotoCommentFunc + +type NewAudioFunc func(*api.API, update.Audio) + +type NewVideoFunc func(*api.API, update.Video) +type VideoCommentFunc func(*api.API, update.VideoComment) +type EditVideoCommentFunc VideoCommentFunc +type RestoreVideoCommentFunc VideoCommentFunc +type DeleteVideoCommentFunc func(*api.API, update.DeleteVideoComment) + +type PostFunc func(*api.API, update.Post) +type RepostFunc PostFunc +type PostCommentFunc func(*api.API, update.PostComment) +type EditPostCommentFunc PostCommentFunc +type RestorePostCommentFunc PostCommentFunc +type DeletePostCommentFunc func(*api.API, update.DeletePostComment) + +type LikeFunc func(*api.API, update.Like) +type UnlikeFunc func(*api.API, update.Unlike) + +type BoardCommentFunc func(*api.API, update.BoardComment) +type EditBoardCommentFunc BoardCommentFunc +type RestoreBoardCommentFunc BoardCommentFunc +type DeleteBoardCommentFunc func(*api.API, update.DeleteBoardComment) + +type MarketCommentFunc func(*api.API, update.MarketComment) +type EditMarketCommentFunc MarketCommentFunc +type RestoreMarketCommentFunc MarketCommentFunc +type DeleteMarketCommentFunc func(*api.API, update.DeleteMarketComment) + +type OrderMarketFunc func(*api.API, update.OrderMarket) +type EditOrderMarketFunc OrderMarketFunc + +type JoinGroupFunc func(*api.API, update.JoinGroup) +type LeaveGroupFunc func(*api.API, update.LeaveGroup) + +type BlockUserFunc func(*api.API, update.BlockUser) +type UnblockUserFunc func(*api.API, update.UnblockUser) + +type VoteFunc func(*api.API, update.Vote) +type EditOwnersFunc func(*api.API, update.EditOwners) +type ControlGroupFunc func(*api.API, update.ControlGroup) +type ChangeGroupPhotoFunc func(*api.API, update.ChangeGroupPhoto) +type VKPayTransactionFunc func(*api.API, update.VKPayTransaction) +type AppNotificationFunc func(*api.API, update.AppNotification) + +type DonateFunc func(*api.API, update.ProlongedDonate) +type ProlongedDonateFunc func(*api.API, update.ProlongedDonate) +type ExpiredDonateFunc func(*api.API, update.ExpiredDonate) +type CancelDonateFunc func(*api.API, update.ExpiredDonate) +type ChangeDonatePriceFunc func(*api.API, update.ChangeDonatePrice) +type WithdrawMoneyFunc func(*api.API, update.WithdrawMoney) +type WithdrawMoneyErrorFunc func(*api.API, update.WithdrawMoneyError) + +func NewScene() *Scenes { + return new(Scenes) +} diff --git a/scene/use.go b/scene/use.go new file mode 100644 index 0000000..54d57e6 --- /dev/null +++ b/scene/use.go @@ -0,0 +1,725 @@ +package scene + +import ( + "encoding/json" + "fmt" + + "github.com/aejoy/vkgo/api" + "github.com/aejoy/vkgo/update" +) + +func newMessage(bot *api.API, thisUpdate update.Update, scenes Scenes) { + object := update.Object{} + if err := json.Unmarshal(thisUpdate.Object, &object); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("NewMessage error is %s", err.Error())) + return + } + + object.Message.Payload, _ = update.DecodePayload(object.Message.RawPayload) + + if scenes.MessageFunc != nil { + scenes.MessageFunc(bot, object.Message) + } +} + +func replyMessage(bot *api.API, thisUpdate update.Update, scenes Scenes) { + object := update.Message{} + if err := json.Unmarshal(thisUpdate.Object, &object); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MessageReply error is %s", err.Error())) + return + } + + object.Payload, _ = update.DecodePayload(object.RawPayload) + + if scenes.ReplyMessageFunc != nil { + scenes.ReplyMessageFunc(bot, object) + } +} + +func editMessage(bot *api.API, thisUpdate update.Update, scenes Scenes) { + object := update.Message{} + if err := json.Unmarshal(thisUpdate.Object, &object); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MessageEdit error is %s", err.Error())) + return + } + + object.Payload, _ = update.DecodePayload(object.RawPayload) + + if scenes.EditMessageFunc != nil { + scenes.EditMessageFunc(bot, object) + } +} + +func enableMessage(bot *api.API, thisUpdate update.Update, scenes Scenes) { + enableMessage := update.EnableMessage{} + if err := json.Unmarshal(thisUpdate.Object, &enableMessage); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MessageAllow error is %s", err.Error())) + return + } + + if scenes.EnableMessageFunc != nil { + scenes.EnableMessageFunc(bot, enableMessage) + } +} + +func disableMessage(bot *api.API, thisUpdate update.Update, scenes Scenes) { + disableMessage := update.DisableMessage{} + if err := json.Unmarshal(thisUpdate.Object, &disableMessage); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MessageDeny error is %s", err.Error())) + return + } + + if scenes.DisableMessageFunc != nil { + scenes.DisableMessageFunc(bot, disableMessage) + } +} + +func typingMessage(bot *api.API, thisUpdate update.Update, scenes Scenes) { + typing := update.Typing{} + if err := json.Unmarshal(thisUpdate.Object, &typing); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MessageTyping error is %s", err.Error())) + return + } + + if scenes.TypingMessageFunc != nil { + scenes.TypingMessageFunc(bot, typing) + } +} + +func eventMessage(bot *api.API, thisUpdate update.Update, scenes Scenes) { + callback := update.Callback{} + if err := json.Unmarshal(thisUpdate.Object, &callback); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MessageEvent error is %s", err.Error())) + return + } + + callback.Payload, _ = update.DecodePayload(callback.RawPayload) + + if scenes.CallbackFunc != nil { + scenes.CallbackFunc(bot, callback) + } +} + +func newPhoto(bot *api.API, thisUpdate update.Update, scenes Scenes) { + photo := update.Photo{} + if err := json.Unmarshal(thisUpdate.Object, &photo); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("PhotoNew error is %s", err.Error())) + return + } + + if scenes.PhotoFunc != nil { + scenes.PhotoFunc(bot, photo) + } +} + +func newPhotoComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.PhotoComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("PhotoCommentNew error is %s", err.Error())) + return + } + + if scenes.PhotoCommentFunc != nil { + scenes.PhotoCommentFunc(bot, comment) + } +} + +func editPhotoComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.PhotoComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("PhotoCommentEdit error is %s", err.Error())) + return + } + + if scenes.EditPhotoCommentFunc != nil { + scenes.EditPhotoCommentFunc(bot, comment) + } +} + +func restorePhotoComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.PhotoComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("PhotoCommentRestore error is %s", err.Error())) + return + } + + if scenes.RestorePhotoCommentFunc != nil { + scenes.RestorePhotoCommentFunc(bot, comment) + } +} + +func deletePhotoComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.PhotoComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("PhotoCommentDelete error is %s", err.Error())) + return + } + + if scenes.DeletePhotoCommentFunc != nil { + scenes.DeletePhotoCommentFunc(bot, comment) + } +} + +func newAudio(bot *api.API, thisUpdate update.Update, scenes Scenes) { + audio := update.Audio{} + if err := json.Unmarshal(thisUpdate.Object, &audio); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("AudioNew error is %s", err.Error())) + return + } + + if scenes.NewAudioFunc != nil { + scenes.NewAudioFunc(bot, audio) + } +} + +func newVideo(bot *api.API, thisUpdate update.Update, scenes Scenes) { + video := update.Video{} + if err := json.Unmarshal(thisUpdate.Object, &video); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("VideoNew error is %s", err.Error())) + return + } + + if scenes.NewVideoFunc != nil { + scenes.NewVideoFunc(bot, video) + } +} + +func newVideoComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.VideoComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("VideoCommentNew error is %s", err.Error())) + return + } + + if scenes.VideoCommentFunc != nil { + scenes.VideoCommentFunc(bot, comment) + } +} + +func editVideoComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.VideoComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("VideoCommentEdit error is %s", err.Error())) + return + } + + if scenes.EditVideoCommentFunc != nil { + scenes.EditVideoCommentFunc(bot, comment) + } +} + +func restoreVideoComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.VideoComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("VideoCommentRestore error is %s", err.Error())) + return + } + + if scenes.RestoreVideoCommentFunc != nil { + scenes.RestoreVideoCommentFunc(bot, comment) + } +} + +func deleteVideoComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.DeleteVideoComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("VideoCommentDelete error is %s", err.Error())) + return + } + + if scenes.DeleteVideoCommentFunc != nil { + scenes.DeleteVideoCommentFunc(bot, comment) + } +} + +func newWallPost(bot *api.API, thisUpdate update.Update, scenes Scenes) { + post := update.Post{} + if err := json.Unmarshal(thisUpdate.Object, &post); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("WallPostNew error is %s", err.Error())) + return + } + + if scenes.PostFunc != nil { + scenes.PostFunc(bot, post) + } +} + +func repostWall(bot *api.API, thisUpdate update.Update, scenes Scenes) { + post := update.Post{} + if err := json.Unmarshal(thisUpdate.Object, &post); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("WallRepost error is %s", err.Error())) + return + } + + if scenes.RepostFunc != nil { + scenes.RepostFunc(bot, post) + } +} + +func newWallReply(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.PostComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("WallReplyNew error is %s", err.Error())) + return + } + + if scenes.PostCommentFunc != nil { + scenes.PostCommentFunc(bot, comment) + } +} + +func editWallReply(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.PostComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("WallReplyEdit error is %s", err.Error())) + return + } + + if scenes.EditPostCommentFunc != nil { + scenes.EditPostCommentFunc(bot, comment) + } +} + +func restoreWallReply(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.PostComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("WallReplyRestore error is %s", err.Error())) + return + } + + if scenes.RestorePostCommentFunc != nil { + scenes.RestorePostCommentFunc(bot, comment) + } +} + +func deleteWallReply(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.DeletePostComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("WallReplyDelete error is %s", err.Error())) + return + } + + if scenes.DeletePostCommentFunc != nil { + scenes.DeletePostCommentFunc(bot, comment) + } +} + +func like(bot *api.API, thisUpdate update.Update, scenes Scenes) { + like := update.Like{} + if err := json.Unmarshal(thisUpdate.Object, &like); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("LikeAdd error is %s", err.Error())) + return + } + + if scenes.LikeFunc != nil { + scenes.LikeFunc(bot, like) + } +} + +func unlike(bot *api.API, thisUpdate update.Update, scenes Scenes) { + unlike := update.Unlike{} + if err := json.Unmarshal(thisUpdate.Object, &unlike); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("LikeRemove error is %s", err.Error())) + return + } + + if scenes.UnlikeFunc != nil { + scenes.UnlikeFunc(bot, unlike) + } +} + +func newBoardPost(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.BoardComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("BoardPostNew error is %s", err.Error())) + return + } + + if scenes.BoardCommentFunc != nil { + scenes.BoardCommentFunc(bot, comment) + } +} + +func editBoardPost(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.BoardComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("BoardPostEdit error is %s", err.Error())) + return + } + + if scenes.EditBoardCommentFunc != nil { + scenes.EditBoardCommentFunc(bot, comment) + } +} + +func restoreBoardPost(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.BoardComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("BoardPostRestore error is %s", err.Error())) + return + } + + if scenes.RestoreBoardCommentFunc != nil { + scenes.RestoreBoardCommentFunc(bot, comment) + } +} + +func deleteBoardPost(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.DeleteBoardComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("BoardPostDelete error is %s", err.Error())) + return + } + + if scenes.DeleteBoardCommentFunc != nil { + scenes.DeleteBoardCommentFunc(bot, comment) + } +} + +func marketComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.MarketComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MarketComment error is %s", err.Error())) + return + } + + if scenes.MarketCommentFunc != nil { + scenes.MarketCommentFunc(bot, comment) + } +} + +func editMarketComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.MarketComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MarketCommentEdit error is %s", err.Error())) + return + } + + if scenes.EditMarketCommentFunc != nil { + scenes.EditMarketCommentFunc(bot, comment) + } +} + +func restoreMarketComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.MarketComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MarketCommentRestore error is %s", err.Error())) + return + } + + if scenes.RestoreMarketCommentFunc != nil { + scenes.RestoreMarketCommentFunc(bot, comment) + } +} + +func deleteMarketComment(bot *api.API, thisUpdate update.Update, scenes Scenes) { + comment := update.DeleteMarketComment{} + if err := json.Unmarshal(thisUpdate.Object, &comment); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MarketCommentDelete error is %s", err.Error())) + return + } + + if scenes.DeleteMarketCommentFunc != nil { + scenes.DeleteMarketCommentFunc(bot, comment) + } +} + +func newMarketOrder(bot *api.API, thisUpdate update.Update, scenes Scenes) { + order := update.OrderMarket{} + if err := json.Unmarshal(thisUpdate.Object, &order); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MarketOrderNew error is %s", err.Error())) + return + } + + if scenes.OrderMarketFunc != nil { + scenes.OrderMarketFunc(bot, order) + } +} + +func editMarketOrder(bot *api.API, thisUpdate update.Update, scenes Scenes) { + order := update.OrderMarket{} + if err := json.Unmarshal(thisUpdate.Object, &order); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("MarketOrderEdit error is %s", err.Error())) + return + } + + if scenes.EditOrderMarketFunc != nil { + scenes.EditOrderMarketFunc(bot, order) + } +} + +func joinGroup(bot *api.API, thisUpdate update.Update, scenes Scenes) { + group := update.JoinGroup{} + if err := json.Unmarshal(thisUpdate.Object, &group); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("GroupJoin error is %s", err.Error())) + return + } + + if scenes.JoinGroupFunc != nil { + scenes.JoinGroupFunc(bot, group) + } +} + +func leaveGroup(bot *api.API, thisUpdate update.Update, scenes Scenes) { + group := update.LeaveGroup{} + if err := json.Unmarshal(thisUpdate.Object, &group); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("GroupLeave error is %s", err.Error())) + return + } + + if scenes.LeaveGroupFunc != nil { + scenes.LeaveGroupFunc(bot, group) + } +} + +func blockUser(bot *api.API, thisUpdate update.Update, scenes Scenes) { + user := update.BlockUser{} + if err := json.Unmarshal(thisUpdate.Object, &user); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("UserBlock error is %s", err.Error())) + return + } + + if scenes.BlockUserFunc != nil { + scenes.BlockUserFunc(bot, user) + } +} + +func unblockUser(bot *api.API, thisUpdate update.Update, scenes Scenes) { + user := update.UnblockUser{} + if err := json.Unmarshal(thisUpdate.Object, &user); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("UserUnblock error is %s", err.Error())) + return + } + + if scenes.UnblockUserFunc != nil { + scenes.UnblockUserFunc(bot, user) + } +} + +func newVote(bot *api.API, thisUpdate update.Update, scenes Scenes) { + vote := update.Vote{} + if err := json.Unmarshal(thisUpdate.Object, &vote); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("PollVoteNew error is %s", err.Error())) + return + } + + if scenes.VoteFunc != nil { + scenes.VoteFunc(bot, vote) + } +} + +func editOwners(bot *api.API, thisUpdate update.Update, scenes Scenes) { + owners := update.EditOwners{} + if err := json.Unmarshal(thisUpdate.Object, &owners); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("GroupOfficersEdit error is %s", err.Error())) + return + } + + if scenes.EditOwnersFunc != nil { + scenes.EditOwnersFunc(bot, owners) + } +} + +func controlGroup(bot *api.API, thisUpdate update.Update, scenes Scenes) { + group := update.ControlGroup{} + if err := json.Unmarshal(thisUpdate.Object, &group); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("GroupChangeSettings error is %s", err.Error())) + return + } + + if scenes.ControlGroupFunc != nil { + scenes.ControlGroupFunc(bot, group) + } +} + +func changeGroupPhoto(bot *api.API, thisUpdate update.Update, scenes Scenes) { + change := update.ChangeGroupPhoto{} + if err := json.Unmarshal(thisUpdate.Object, &change); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("GroupChangePhoto error is %s", err.Error())) + return + } + + if scenes.ChangeGroupPhotoFunc != nil { + scenes.ChangeGroupPhotoFunc(bot, change) + } +} + +func vkPayTransaction(bot *api.API, thisUpdate update.Update, scenes Scenes) { + transaction := update.VKPayTransaction{} + if err := json.Unmarshal(thisUpdate.Object, &transaction); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("VKPayTransaction error is %s", err.Error())) + return + } + + if scenes.VKPayTransactionFunc != nil { + scenes.VKPayTransactionFunc(bot, transaction) + } +} + +func appNotification(bot *api.API, thisUpdate update.Update, scenes Scenes) { + notification := update.AppNotification{} + if err := json.Unmarshal(thisUpdate.Object, ¬ification); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("AppPayload error is %s", err.Error())) + return + } + + if scenes.AppNotificationFunc != nil { + scenes.AppNotificationFunc(bot, notification) + } +} + +func donate(bot *api.API, thisUpdate update.Update, scenes Scenes) { + donate := update.ProlongedDonate{} + if err := json.Unmarshal(thisUpdate.Object, &donate); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("DonutSubscriptionCreate error is %s", err.Error())) + return + } + + if scenes.DonateFunc != nil { + scenes.DonateFunc(bot, donate) + } +} + +func prolongedDonate(bot *api.API, thisUpdate update.Update, scenes Scenes) { + donate := update.ProlongedDonate{} + if err := json.Unmarshal(thisUpdate.Object, &donate); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("DonutSubscriptionProlonged error is %s", err.Error())) + return + } + + if scenes.ProlongedDonateFunc != nil { + scenes.ProlongedDonateFunc(bot, donate) + } +} + +func expiredDonate(bot *api.API, thisUpdate update.Update, scenes Scenes) { + donate := update.ExpiredDonate{} + if err := json.Unmarshal(thisUpdate.Object, &donate); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("DonutSubscriptionExpired error is %s", err.Error())) + return + } + + if scenes.ExpiredDonateFunc != nil { + scenes.ExpiredDonateFunc(bot, donate) + } +} + +func cancelDonate(bot *api.API, thisUpdate update.Update, scenes Scenes) { + donate := update.ExpiredDonate{} + if err := json.Unmarshal(thisUpdate.Object, &donate); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("DonutSubscriptionCancelled error is %s", err.Error())) + return + } + + if scenes.CancelDonateFunc != nil { + scenes.CancelDonateFunc(bot, donate) + } +} + +func changeDonatePrice(bot *api.API, thisUpdate update.Update, scenes Scenes) { + donate := update.ChangeDonatePrice{} + if err := json.Unmarshal(thisUpdate.Object, &donate); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("DonutSubscriptionPriceChanged error is %s", err.Error())) + return + } + + if scenes.ChangeDonatePriceFunc != nil { + scenes.ChangeDonatePriceFunc(bot, donate) + } +} + +func withdrawMoney(bot *api.API, thisUpdate update.Update, scenes Scenes) { + money := update.WithdrawMoney{} + if err := json.Unmarshal(thisUpdate.Object, &money); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("DonutMoneyWithdraw error is %s", err.Error())) + return + } + + if scenes.WithdrawMoneyFunc != nil { + scenes.WithdrawMoneyFunc(bot, money) + } +} + +func withdrawMoneyError(bot *api.API, thisUpdate update.Update, scenes Scenes) { + money := update.WithdrawMoneyError{} + if err := json.Unmarshal(thisUpdate.Object, &money); err != nil { + bot.Client.Logger.Error(fmt.Sprintf("DonutMoneyWithdrawError error is %s", err.Error())) + return + } + + if scenes.WithdrawMoneyErrorFunc != nil { + scenes.WithdrawMoneyErrorFunc(bot, money) + } +} + +func Use(bot *api.API, thisUpdate update.Update, scenes Scenes) { + if bot.Client.Logger != nil { + event, _ := json.Marshal(thisUpdate) + bot.Client.Logger.Info(fmt.Sprintf("Updates response is %s", string(event))) + } + + handler := getScenesHandlers(thisUpdate.Type) + if handler != nil { + handler(bot, thisUpdate, scenes) + } +} + +func getScenesHandlers(typ string) Func { + scenesHandlers := map[string]Func{ + "message_new": newMessage, + "message_reply": replyMessage, + "message_edit": editMessage, + "message_allow": enableMessage, + "message_deny": disableMessage, + "message_typing_state": typingMessage, + "message_event": eventMessage, + "photo_new": newPhoto, + "photo_comment_new": newPhotoComment, + "photo_comment_edit": editPhotoComment, + "photo_comment_restore": restorePhotoComment, + "photo_comment_delete": deletePhotoComment, + "audio_new": newAudio, + "video_new": newVideo, + "video_comment_new": newVideoComment, + "video_comment_edit": editVideoComment, + "video_comment_restore": restoreVideoComment, + "video_comment_delete": deleteVideoComment, + "wall_post_new": newWallPost, + "wall_repost": repostWall, + "wall_reply_new": newWallReply, + "wall_reply_edit": editWallReply, + "wall_reply_restore": restoreWallReply, + "wall_reply_delete": deleteWallReply, + "like_add": like, + "like_remove": unlike, + "board_post_new": newBoardPost, + "board_post_edit": editBoardPost, + "board_post_restore": restoreBoardPost, + "board_post_delete": deleteBoardPost, + "market_comment": marketComment, + "market_comment_edit": editMarketComment, + "market_comment_restore": restoreMarketComment, + "market_comment_delete": deleteMarketComment, + "market_order_new": newMarketOrder, + "market_order_edit": editMarketOrder, + "group_join": joinGroup, + "group_leave": leaveGroup, + "user_block": blockUser, + "user_unblock": unblockUser, + "poll_vote_new": newVote, + "group_officers_edit": editOwners, + "group_change_settings": controlGroup, + "group_change_photo": changeGroupPhoto, + "vkpay_transaction": vkPayTransaction, + "app_payload": appNotification, + "donut_subscription_create": donate, + "donut_subscription_prolonged": prolongedDonate, + "donut_subscription_expired": expiredDonate, + "donut_subscription_cancelled": cancelDonate, + "donut_subscription_price_changed": changeDonatePrice, + "donut_money_withdraw": withdrawMoney, + "donut_money_withdraw_error": withdrawMoneyError, + } + + return scenesHandlers[typ] +} diff --git a/template/carousel.go b/template/carousel.go new file mode 100644 index 0000000..61af982 --- /dev/null +++ b/template/carousel.go @@ -0,0 +1,193 @@ +package template + +import ( + "fmt" + + "github.com/aejoy/vkgo/keyboard" +) + +// NewCarousel 🐸 creates a carousel object based on the Template structure +// 🍄 This is the easiest way to work with carousels +// 🌷 Does not require manual placement of elements, specifying the type, etc. +// 🌈 Pre-created elements can be used as arguments +// 🦌 Always returns a pointer to a Template object 🦋. +func NewCarousel(properties ...any) *Template { + properties = append(properties, "carousel") + return New(properties...) +} + +// Title - 🍥 element header. +type Title string + +// Description - 🍜 element description. +type Description string + +// PhotoID - 🦊 VK photo ID format «#owner_id_#photo_id». +type PhotoID string + +// Photo - ⛩️ VK photo ID format «#owner_id_#photo_id». +type Photo string + +// Element - adding a new element to the template +// Accepted values: +// String - 1: Title, 2 - Description, 3 - PhotoID +// Element - element of the element to be added +// Action - action when clicking on the Action element +// keyboard.Buttons - vertical set of buttons +// *keyboard.Buttons - the same, but via the pointer +// Also available are custom types which are listed in the String argument +// Returns modified Template object with a new element. +func (template *Template) Element(properties ...any) *Template { + element := Element{} + + for _, property := range properties { + switch property := property.(type) { + case string: + switch { + case element.Title == "": + element.Title = property + case element.Description == "": + element.Description = property + default: + element.PhotoID = property + } + case Element: + element = property + case Action: + element.Action = property + case keyboard.Buttons: + value := property + element.Buttons = &value + case *keyboard.Buttons: + element.Buttons = property + case Title: + element.Title = string(property) + case Description: + element.Description = string(property) + case Photo: + element.PhotoID = string(property) + case PhotoID: + element.PhotoID = string(property) + } + } + + return template.Add(element) +} + +func (template *Template) Title(properties ...any) *Template { + var title string + + for _, property := range properties { + switch property := property.(type) { + case string: + title = property + case Title: + title = string(property) + } + } + + if count := len(template.Elements); count > 0 { + element := &template.Elements[count-1] + element.Title = title + } + + return template +} + +func (template *Template) Description(properties ...any) *Template { + var description string + + for _, property := range properties { + switch property := property.(type) { + case string: + description = property + case Description: + description = string(property) + } + } + + if count := len(template.Elements); count > 0 { + element := &template.Elements[count-1] + element.Description = description + } + + return template +} + +func (template *Template) Photo(properties ...any) *Template { + var photo string + + for _, property := range properties { + switch property := property.(type) { + case string: + photo = property + case Title: + photo = string(property) + } + } + + if count := len(template.Elements); count > 0 { + element := &template.Elements[count-1] + element.PhotoID = photo + } + + return template +} + +// Add append an element to the template Elements. +func (template *Template) Add(element Element) *Template { + template.Elements = append(template.Elements, element) + return template +} + +const ( + LINK = "open_link" + PHOTO = "open_photo" +) + +// Action - 🌴 method of creating an action with a template element +// 🏖️ Accepts the following arguments: +// 🍹 Action Structure +// 😎 String - 1: Type, 2: Link +// 🚎 And the custom types described in the String argument +// 🦩 Returns the modified pattern by setting the Action to the last element. +func (template *Template) Action(properties ...any) *Template { + action := Action{} + + for _, property := range properties { + if typ := fmt.Sprintf("%T", property); typ == "string" { + if action.Type == "" { + action.Type = property.(string) + } else { + action.Link = property.(string) + } + } + } + + if count := len(template.Elements); count > 0 { + element := &template.Elements[count-1] + element.Action = action + } + + return template +} + +// Buttons - 🤡 add buttons to the last created carousel element +// 🍔 Accepts arguments: * Keyboard.Buttons +// 🍟 Returns the modified template. +func (template *Template) Buttons(properties ...any) *Template { + buttons := &keyboard.Buttons{} + + for _, property := range properties { + if property, ok := property.(*keyboard.Buttons); ok { + buttons = property + } + } + + if count := len(template.Elements); count > 0 { + element := &template.Elements[count-1] + element.Buttons = buttons + } + + return template +} diff --git a/template/template.go b/template/template.go new file mode 100644 index 0000000..d6dae61 --- /dev/null +++ b/template/template.go @@ -0,0 +1,66 @@ +package template + +import ( + "encoding/json" + + "github.com/aejoy/vkgo/keyboard" +) + +// Template 🍂 presents VK API template objects +// ☠️ Type specifies the type of template to create. Available Type: «carousel» +// 🎃 Elements - the list of Element objects arranged horizontally in the carousel. +type Template struct { + Type string `json:"type"` + Elements []Element `json:"elements"` +} + +// Element 💐 is a carousel object that is displayed horizontally +// 🌈 Title - element header. Limited to 80 characters +// 🐰 Description - element description. Limited to 80 characters +// 🌷 PhotoID - VK photo ID format «#owner_id_#photo_id» +// 🐇 Action - the action that should happen when you click on the element +// 🐣 Buttons - pointer to the buttons from the «Keyboard» package, which are arranged vertically. +type Element struct { + Title string `json:"title"` + Description string `json:"description"` + PhotoID string `json:"photo_id"` + Action Action `json:"action"` + Buttons *keyboard.Buttons `json:"buttons"` +} + +// Action - 🌲 action when clicking on a carousel element +// 🌱 Type - action type. Available: open_link or open_photo +// 🌳 OpenLink opens a link, OpenPhoto opens a photo of the object +// 👩‍🌾 Link - link with the type «open_link». Important: not «open_photo». +type Action struct { + Type string `json:"type"` + Link string `json:"link,omitempty"` +} + +// New 🌷 is responsible for creating the template +// 🌈 It takes String - type Template and optional type []Element +// 🌺 Returns a pointer to the Template object. +func New(properties ...any) *Template { + template := Template{Elements: []Element{}} + + for _, property := range properties { + switch property := property.(type) { + case string: + template.Type = property + case []Element: + template.Elements = property + } + } + + return &template +} + +// JSON 🍷🧣🍁 turns an object into a JSON format string. +func (template *Template) JSON() string { + data, err := json.Marshal(template) + if err != nil { + return "" + } + + return string(data) +} diff --git a/tests/api_test.go b/tests/api_test.go new file mode 100644 index 0000000..fe10c70 --- /dev/null +++ b/tests/api_test.go @@ -0,0 +1,27 @@ +package tests_test + +import ( + "fmt" + "os" + "testing" + + "github.com/aejoy/vkgo/api" + + "github.com/stretchr/testify/assert" +) + +func TestConnection(t *testing.T) { + t.Run("UserBot", func(t *testing.T) { + fmt.Println("USER_TOKEN=", os.Getenv("USER_TOKEN")) + + _, err := api.New(os.Getenv("USER_TOKEN")) + assert.Equal(t, true, err == nil, err) + }) + + t.Run("CommunityBot", func(t *testing.T) { + fmt.Println("GROUP_TOKEN=", os.Getenv("GROUP_TOKEN")) + + _, err := api.New(os.Getenv("GROUP_TOKEN")) + assert.Equal(t, true, err == nil, err) + }) +} diff --git a/tests/schema_test.go b/tests/schema_test.go new file mode 100644 index 0000000..fac6655 --- /dev/null +++ b/tests/schema_test.go @@ -0,0 +1,28 @@ +package tests_test + +import ( + "net/url" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/botscommunity/botsgo/pkg/schema" +) + +func TestSchema(t *testing.T) { + t.Run("typeDefs", func(t *testing.T) { + query := make(url.Values) + + schema.NewSchema(schema.TypeDefs{ + schema.Integer: schema.NewType(schema.ParameterNames{"chat_ids", "chat_message_id", "offset", "count"}), + schema.String: schema.NewType(schema.ParameterNames{"text"}), + schema.ArrayString: schema.NewType(schema.ParameterNames{"attachments"}), + schema.ArrayInteger: schema.NewType(schema.ParameterNames{"chat_ids"}), + schema.Struct: nil, + }).ConvertToQuery(query, []int{1, 2, 3}, 1, struct { + Text string `json:"text"` + }{Text: "meow :3"}) + + assert.Equal(t, true, query.Encode() == "chat_ids=1%2C2%2C3&chat_message_id=1&text=meow+%3A3", "Schema is broken") + }) +} diff --git a/types/account.go b/types/account.go new file mode 100644 index 0000000..09bc920 --- /dev/null +++ b/types/account.go @@ -0,0 +1,63 @@ +package types + +// ChangePassword + +type ChangePassword struct { + RestoreSID string `json:"restore_sid"` + ChangePasswordHash string `json:"change_password_hash"` + CurrentPassword string `json:"old_password"` + NewPassword string `json:"new_password"` +} + +// GetActiveOffers + +type ActiveOffers struct { + Offset int `json:"offset"` + Count int `json:"count"` +} + +// GetBans + +type Bans struct { + Offset int `json:"offset"` + Count int `json:"count"` +} + +// GetInfo + +type Info struct { + Fields []string `json:"fields"` +} + +// EditProfileInfo + +type EditProfileInfo struct { + Name string `json:"first_name"` + Surname string `json:"last_name"` + MaidenName string `json:"maiden_name"` + Domain string `json:"screen_name"` + CancelRequestID int `json:"cancel_request_id"` + Sex int `json:"sex"` + Relation int `json:"relation"` + RelationPartnerID int `json:"relation_partner_id"` + Birthdate string `json:"bdate"` + BirthdateVisibility int `json:"bdate_visibility"` + HomeTown string `json:"home_town"` + CountryID int `json:"country_id"` + CityID int `json:"city_id"` + Status string `json:"status"` +} + +// EditAccountInfo + +type EditAccountInfo struct { + Intro int `json:"intro"` + OnlyMyPosts int `json:"own_posts_default"` + NoWallReplise int `json:"no_wall_replies"` + Name string `json:"name"` + Value string `json:"value"` +} + +type SetOnline struct { + Calls bool `json:"voip" to:"int"` +} diff --git a/types/banUser.go b/types/banUser.go new file mode 100644 index 0000000..31003c8 --- /dev/null +++ b/types/banUser.go @@ -0,0 +1,14 @@ +package types + +type BanUserComment struct { + Text string `json:"text"` + Show bool `json:"show"` +} + +type BanUsers struct { + GroupID int `json:"group_id"` + UserID int `json:"user_id"` + Offset int `json:"offset"` + Count int `json:"count"` + Fields []string `json:"fields"` +} diff --git a/types/execute.go b/types/execute.go new file mode 100644 index 0000000..9dbb641 --- /dev/null +++ b/types/execute.go @@ -0,0 +1,6 @@ +package types + +type Execute struct { + Code any `json:"code"` + Version string `json:"func_v"` +} diff --git a/types/friends.go b/types/friends.go new file mode 100644 index 0000000..78651e5 --- /dev/null +++ b/types/friends.go @@ -0,0 +1,117 @@ +package types + +// AddFriend + +type AddFriend struct { + UserID int `json:"user_id"` + Text string `json:"text"` + Follow bool `json:"follow" to:"int"` +} + +// AddFriendsList + +type AddFriendsList struct { + Name string `json:"name"` + UserIDs []string `json:"user_ids"` +} + +// AreFriends + +type AreFriends struct { + UserIDs []string `json:"user_ids"` + NeedSign int `json:"need_sign"` +} + +// EditFriends + +type EditFriends struct { + UserID int `json:"user_id"` + ListIDs []int `json:"list_ids"` +} + +// EditFriendsList + +type EditFriendsList struct { + Name string `json:"name"` + ListID int `json:"list_id"` + UserIDs []int `json:"user_ids"` + AddUserIDs []int `json:"add_user_ids"` + DeleteUserIDs []int `json:"delete_user_ids"` +} + +// GetFriends + +type Friends struct { + UserID int `json:"user_id"` + Order string `json:"order"` + ListID int `json:"list_id"` + Count int `json:"count"` + Offset int `json:"offset"` + Fields []string `json:"fields"` + NameCase string `json:"name_case"` + Ref string `json:"ref"` +} + +// GetFriendsLists + +type FriendsList struct { + UserID int `json:"user_id"` + ReturnSystem int `json:"return_system"` +} + +// GetMutualFriends + +type MutualFriends struct { + SourceUID int `json:"source_uid"` + TargetUIDs []int `json:"target_uids"` + Order string `json:"order"` + Count int `json:"count"` + Offset int `json:"offset"` + NeedCommonCount bool `json:"need_common_count" to:"int"` +} + +// GetOnlineFriends + +type OnlineFriends struct { + UserID int `json:"user_id"` + ListID int `json:"list_id"` + Order string `json:"order"` + Count int `json:"count"` + Offset int `json:"offset"` +} + +// GetRecentFriends + +// GetFriendsRequests + +type FriendsRequests struct { + Offset int `json:"offset"` + Count int `json:"count"` + NeedMutual bool `json:"need_mutual" to:"int"` + Out bool `json:"out" to:"int"` + Sort int `json:"sort"` + NeedViewed bool `json:"need_viewed" to:"int"` + Ref string `json:"ref"` + Fields string `json:"fields"` +} + +// GetSuggestionsFriends + +type SuggestionsFriends struct { + Filter string `json:"filter"` + Count int `json:"count"` + Offset int `json:"offset"` + Fields string `json:"fields"` + NameCase string `json:"name_case"` +} + +// SearchFriends + +type SearchFriends struct { + UserID int `json:"user_id"` + Q string `json:"q"` + Fields string `json:"fields"` + NameCase string `json:"name_case"` + Offset int `json:"offset"` + Count int `json:"count"` +} diff --git a/types/gifts.go b/types/gifts.go new file mode 100644 index 0000000..b6a2d84 --- /dev/null +++ b/types/gifts.go @@ -0,0 +1,7 @@ +package types + +type Gifts struct { + UserID int `json:"user_id"` + Count int `json:"count"` + Offset int `json:"offset"` +} diff --git a/types/groups.go b/types/groups.go new file mode 100644 index 0000000..05943a7 --- /dev/null +++ b/types/groups.go @@ -0,0 +1,373 @@ +package types + +// AddGroupAddress + +type AddGroupAddress struct { + GroupID int `json:"group_id"` + Title string `json:"title"` + Address string `json:"address"` + AdditionalAddress string `json:"additional_address"` + CountryID int `json:"country_id"` + CityID int `json:"city_id"` + MetroID int `json:"metro_id"` + Latitude string `json:"latitude"` + Longitude string `json:"longitude"` + Phone string `json:"phone"` + WorkInfoStatus string `json:"work_info_status"` + Timetable string `json:"timetable"` + IsMainAddress bool `json:"is_main_address" to:"int"` +} + +// AddGroupCallbackServer + +type AddGroupCallbackServer struct { + GroupID int `json:"group_id"` + URL string `json:"url"` + Title string `json:"title"` + SecretKey string `json:"secret_key"` +} + +// AddGroupLink + +type AddGroupLink struct { + GroupID int `json:"group_id"` + Link string `json:"link"` + Text string `json:"text"` +} + +// ApproveRequestGroup + +type ApproveRequestGroup struct { + GroupID int `json:"group_id"` + UserID int `json:"user_id"` +} + +// BanUser + +type BanUser struct { + GroupID int `json:"group_id"` + OwnerID int `json:"owner_id"` + EndDate int `json:"end_date"` + Reason int `json:"reason"` + Comment string `json:"comment"` + CommentVisible bool `json:"comment_visible" to:"int"` +} + +// CreateGroup + +type CreateGroup struct { + Title string `json:"title"` + Description string `json:"description"` + Type string `json:"type"` + PublicCategory int `json:"public_category"` + PublicSubcategory int `json:"public_subcategory"` + Subtype int `json:"subtype"` +} + +// DeleteGroupAddress + +type DeleteGroupAddress struct { + GroupID int `json:"group_id"` + AddressID int `json:"address_id"` +} + +// DeleteGroupCallbackServer + +type DeleteGroupCallbackServer struct { + GroupID int `json:"group_id"` + ServerID int `json:"server_id"` +} + +// DeleteGroupLink + +type DeleteGroupLink struct { + GroupID int `json:"group_id"` + LinkID int `json:"link_id"` +} + +// EditGroup + +type EditGroup struct { + GroupID int `json:"group_id"` + Title string `json:"title"` + Description string `json:"description"` + ScreenName string `json:"screen_name"` + Access int `json:"access"` + Website string `json:"website"` + Subject int `json:"subject"` + EMail string `json:"email"` + Phone string `json:"phone"` + RSS string `json:"rss"` + EventStartDate int `json:"event_start_date"` + EventFinishDate int `json:"event_finish_date"` + EventGroupID int `json:"event_group_id"` + PublicCategory int `json:"public_category"` + PublicSubcategory int `json:"public_subcategory"` + PublicDate string `json:"public_date"` + Wall int `json:"wall"` + Topics int `json:"topics"` + Photos int `json:"photos"` + Video int `json:"video"` + Audio int `json:"audio"` + Links bool `json:"links" to:"int"` + Events bool `json:"events" to:"int"` + Places bool `json:"places" to:"int"` + Contacts bool `json:"contacts" to:"int"` + Docs int `json:"docs"` + Wiki int `json:"wiki"` + Messages bool `json:"messages" to:"int"` + Articles bool `json:"articles" to:"int"` + Addresses bool `json:"addresses" to:"int"` + AgeLimits int `json:"age_limits"` + Market bool `json:"market" to:"int"` + MarketButtons string `json:"market_buttons"` + MarketComments bool `json:"market_comments" to:"int"` + MarketCountry string `json:"market_country"` + MarketCity string `json:"market_city"` + MarketCurrency int `json:"market_currency"` + MarketContact int `json:"market_contact"` + MarketWiki int `json:"market_wiki"` + ObsceneFilter bool `json:"obscene_filter" to:"int"` + ObsceneStopwords bool `json:"obscene_stopwords" to:"int"` + ToxicFilter bool `json:"toxic_filter" to:"int"` + DisableRepliesFromGroups bool `json:"disable_replies_from_groups" to:"int"` + ObsceneWord string `json:"obscene_word"` + MainSection int `json:"main_section"` + SecondarySection int `json:"secondary_section"` + Country int `json:"country"` + City int `json:"city"` +} + +// EditGroupCallbackServer + +type EditGroupCallbackServer struct { + GroupID int `json:"group_id"` + ServerID int `json:"server_id"` + URL string `json:"url"` + Title string `json:"title"` + SecretKey string `json:"secret_key"` +} + +// EditGroupLink + +type EditGroupLink struct { + GroupID int `json:"group_id"` + LinkID int `json:"link_id"` + Text string `json:"text"` +} + +// EditGroupManager + +type EditGroupManager struct { + GroupID int `json:"group_id"` + UserID int `json:"user_id"` + Role string `json:"role"` + IsContact bool `json:"is_contact" to:"int"` + ContactPosition string `json:"contact_position"` + ContactPhone string `json:"contact_phone"` + ContactEMail string `json:"contact_email"` +} + +// GetUserGroups + +type GetUserGroups struct { + UserID int `json:"user_id"` + Extended bool `json:"extended" to:"int"` + Filter string `json:"filter"` + Fields []string `json:"fields"` + Offset int `json:"offset"` + Count int `json:"count"` +} + +// GetGroupAddresses + +type GetGroupAddresses struct { + GroupID int `json:"group_id"` + AddressIDs []any `json:"address_ids"` + Latitude string `json:"latitude"` + Longitude string `json:"longitude"` + Offset int `json:"offset"` + Count int `json:"count"` + Fields []string `json:"fields"` +} + +// GetBannedUsers + +type GetBannedUsers struct { + GroupID int `json:"group_id"` + Offset int `json:"offset"` + Count int `json:"count"` + Fields []string `json:"fields"` + OwnerID int `json:"owner_id"` +} + +// GetGroup, GetGroups + +type GetGroups struct { + GroupIDs string `json:"group_ids"` + GroupID string `json:"group_id"` + Fields []string `json:"fields"` +} + +// GetGroupCallbackServers + +type GetGroupCallbackServers struct { + GroupID int `json:"group_id"` + ServerIDs []any `json:"server_ids"` +} + +// GetGroupCallbackSettings + +type GetGroupCallbackSettings struct { + GroupID int `json:"group_id"` + ServerID int `json:"server_id"` +} + +// GetGroupCatalogInfo + +type GetGroupCatalogInfo struct { + Extended bool `json:"extended" to:"int"` + Subcategories bool `json:"subcategories" to:"int"` +} + +// GetGroupInvitedUsers + +type GetGroupInvitedUsers struct { + Offset int `json:"offset"` + Count int `json:"count"` + Extended bool `json:"extended" to:"int"` +} + +// GetGroupMembers + +type GetGroupMembers struct { + GroupID int `json:"group_id"` + Sort string `json:"sort"` + Offset int `json:"offset"` + Count int `json:"count"` + Fields []string `json:"fields"` +} + +// GetGroupRequests + +type GetGroupRequests struct { + GroupID int `json:"group_id"` + Offset int `json:"offset"` + Count int `json:"count"` + Fields []string `json:"fields"` +} + +// InviteGroup + +type InviteGroup struct { + GroupID int `json:"group_id"` + UserID int `json:"user_id"` +} + +// IsGroupMember + +type IsGroupMember struct { + GroupID int `json:"group_id"` + UserID int `json:"user_id"` + UserIDs []int `json:"user_i_ds"` +} + +// JoinGroup + +type JoinGroup struct { + GroupID int `json:"group_id"` + NotSure string `json:"not_sure"` +} + +// RemoveGroupUser + +type RemoveGroupUser struct { + GroupID int `json:"group_id"` + UserID int `json:"user_id"` +} + +// ReorderGroupLink + +type ReorderGroupLink struct { + GroupID int `json:"group_id"` + LinkID int `json:"link_id"` + After int `json:"after"` +} + +// SearchGroup + +type SearchGroup struct { + Q string `json:"q"` + Type string `json:"type"` + CountryID int `json:"country_id"` + CityID int `json:"city_id"` + Future bool `json:"future" to:"int"` + Market bool `json:"market" to:"int"` + Sort int `json:"sort"` + Offset int `json:"offset"` + Count int `json:"count"` +} + +// SetGroupLongPollSettings + +type SetGroupLongPollSettings struct { + GroupID int `json:"group_id"` + Enabled bool `json:"enabled" to:"int"` + APIVersion string `json:"api_version"` + MessageNew bool `json:"message_new" to:"int"` + MessageReply bool `json:"message_reply" to:"int"` + MessageAllow bool `json:"message_allow" to:"int"` + MessageDeny bool `json:"message_deny" to:"int"` + MessageEdit bool `json:"message_edit" to:"int"` + MessageTypingState bool `json:"message_typing_state" to:"int"` + PhotoNew bool `json:"photo_new" to:"int"` + AudioNew bool `json:"audio_new" to:"int"` + VideoNew bool `json:"video_new" to:"int"` + WallReplyNew bool `json:"wall_reply_new" to:"int"` + WallReplyEdit bool `json:"wall_reply_edit" to:"int"` + WallReplyDelete bool `json:"wall_reply_delete" to:"int"` + WallReplyRestore bool `json:"wall_reply_restore" to:"int"` + WallPostNew bool `json:"wall_post_new" to:"int"` + WallRepost bool `json:"wall_repost" to:"int"` + BoardPostNew bool `json:"board_post_new" to:"int"` + BoardPostEdit bool `json:"board_post_edit" to:"int"` + BoardPostRestore bool `json:"board_post_restore" to:"int"` + BoardPostDelete bool `json:"board_post_delete" to:"int"` + PhotoCommentNew bool `json:"photo_comment_new" to:"int"` + PhotoCommentEdit bool `json:"photo_comment_edit" to:"int"` + PhotoCommentDelete bool `json:"photo_comment_delete" to:"int"` + PhotoCommentRestore bool `json:"photo_comment_restore" to:"int"` + VideoCommentNew bool `json:"video_comment_new" to:"int"` + VideoCommentEdit bool `json:"video_comment_edit" to:"int"` + VideoCommentDelete bool `json:"video_comment_delete" to:"int"` + VideoCommentRestore bool `json:"video_comment_restore" to:"int"` + MarketCommentNew bool `json:"market_comment_new" to:"int"` + MarketCommentEdit bool `json:"market_comment_edit" to:"int"` + MarketCommentDelete bool `json:"market_comment_delete" to:"int"` + MarketCommentRestore bool `json:"market_comment_restore" to:"int"` + PollVoteNew bool `json:"poll_vote_new" to:"int"` + GroupJoin bool `json:"group_join" to:"int"` + GroupLeave bool `json:"group_leave" to:"int"` + GroupChangeSettings bool `json:"group_change_settings" to:"int"` + GroupChangePhoto bool `json:"group_change_photo" to:"int"` + GroupOfficersEdit bool `json:"group_officers_edit" to:"int"` + UserBlock bool `json:"user_block" to:"int"` + UserUnblock bool `json:"user_unblock" to:"int"` + LikeAdd bool `json:"like_add" to:"int"` + LikeRemove bool `json:"like_remove" to:"int"` + MessageEvent bool `json:"message_event" to:"int"` + DonutSubscriptionCreate bool `json:"donut_subscription_create" to:"int"` + DonutSubscriptionProlonged bool `json:"donut_subscription_prolonged" to:"int"` + DonutSubscriptionCancelled bool `json:"donut_subscription_cancelled" to:"int"` + DonutSubscriptionPriceChanged bool `json:"donut_subscription_price_changed" to:"int"` + DonutSubscriptionExpired bool `json:"donut_subscription_expired" to:"int"` + DonutMoneyWithdraw bool `json:"donut_money_withdraw" to:"int"` + DonutMoneyWithdrawError bool `json:"donut_money_withdraw_error" to:"int"` +} + +// UnbanUser + +type UnbanUser struct { + GroupID int `json:"group_id"` + OwnerID int `json:"owner_id"` +} diff --git a/types/historyMessages.go b/types/historyMessages.go new file mode 100644 index 0000000..6bbbd8b --- /dev/null +++ b/types/historyMessages.go @@ -0,0 +1,12 @@ +package types + +type HistoryMessages struct { + GroupID int `json:"group_id"` + ChatID int `json:"peer_id"` + UserID int `json:"user_id"` + StartMessageID int `json:"start_message_id"` + Offset int `json:"offset"` + Count int `json:"count"` + Rev bool `json:"rev"` + Fields []string `json:"fields"` +} diff --git a/types/messages.go b/types/messages.go new file mode 100644 index 0000000..870b333 --- /dev/null +++ b/types/messages.go @@ -0,0 +1,120 @@ +package types + +import ( + "encoding/json" + "time" +) + +type Message struct { + GroupID int `json:"group_id"` + ChatID int `json:"chat_id"` + MessageIDs []int `json:"message_ids"` + ChatMessageIDs []int `json:"cmids"` + Fields []string `json:"fields"` + Extended bool `json:"extended"` + Characters int `json:"characters"` +} + +type UserLongPollServer struct { + GroupID int `json:"group_id"` + Version int `json:"lp_version"` + NeedPTS bool `json:"need_pts"` +} + +type SendMessage struct { + GroupID int `json:"group_id"` + RandomID int `json:"random_id"` + Domain string `json:"domain"` + ChatID int `json:"peer_ids"` + ChatIDs []int `json:"peer_ids"` //nolint:govet + UserID int `json:"user_id"` + UserIDs []int `json:"user_ids"` + Text string `json:"message"` + Latitude string `json:"lat"` + Longitude string `json:"long"` + Attachments []string `json:"attachment"` + Attachment string `json:"attachment"` //nolint:govet + Forward string `json:"forward"` + StickerID int `json:"sticker_id"` + Keyboard string `json:"keyboard"` + Template string `json:"template"` + Payload string `json:"payload"` + ContentSource string `json:"content_source"` + DontParseLinks bool `json:"dont_parse_links" to:"int"` + DisableMentions bool `json:"disable_mentions" to:"int"` + Intent string `json:"intent"` + SubscribeID int `json:"subscribe_id"` + ExpireTime int `json:"expire_ttl"` +} + +type Forward struct { + ChatID int `json:"peer_id"` + ChatMessageID int `json:"conversation_message_ids"` + IsReply bool `json:"is_reply"` +} + +func NewForward(chatID, chatMessageID int, isReply bool) (string, error) { + b, err := json.Marshal(Forward{chatID, chatMessageID, isReply}) + return string(b), err +} + +func NewRandomID() int { + return int(time.Now().UnixNano()) +} + +type EditMessage struct { + GroupID int `json:"group_id"` + ChatID int `json:"peer_id"` + Text string `json:"message"` + MessageID int `json:"message_id"` + ChatMessageID int `json:"conversation_message_id"` + Attachment string `json:"attachment"` + Attachments []string `json:"attachment,omitempty"` //nolint:govet + Template string `json:"template,omitempty"` + Keyboard string `json:"keyboard,omitempty"` + KeepForwardMessages bool `json:"keep_forward_messages,omitempty"` + KeepSnippets bool `json:"keep_snippets,omitempty"` + DontParseLinks bool `json:"dont_parse_links,omitempty"` + DisableMentions bool `json:"disable_mentions,omitempty"` + Latitude string `json:"latitude,omitempty"` + Longitude string `json:"longitude,omitempty"` +} + +type DeleteMessage struct { + GroupID int `json:"group_id"` + ChatID int `json:"peer_id"` + MessageID int `json:"messages_ids"` + MessagesIDs []int `json:"messages_ids"` //nolint:govet + ChatMessageID int `json:"cmids"` + ChatMessagesIDs []int `json:"cmids"` //nolint:govet + Spam bool `json:"spam"` + Everyone bool `json:"delete_for_all"` + Reason int `json:"reason"` +} + +type KickUser struct { + ChatID int `json:"chat_id"` + UserID int `json:"user_id"` + MemberID int `json:"member_id"` +} + +type PinMessage struct { + ChatID int `json:"peer_id"` + MessageID int `json:"message_id"` + ChatMessageID int `json:"conversation_message_id"` +} + +type CreateChat struct { + GroupID int `json:"group_id"` + UserID int `json:"user_ids"` + UserIDs []int `json:"user_ids"` //nolint:govet + Title string `json:"title"` +} + +type ChatMembers struct { + GroupID int `json:"group_id"` + ChatID int `json:"peer_id"` + Offset int `json:"offset"` + Count int `json:"count"` + Fields []string `json:"fields"` +} diff --git a/types/photos.go b/types/photos.go new file mode 100644 index 0000000..7522124 --- /dev/null +++ b/types/photos.go @@ -0,0 +1,25 @@ +package types + +type Albums struct { + OwnerID int `json:"owner_id"` + AlbumsID []int `json:"albums_id"` + Offset int `json:"offset"` + Count int `json:"count"` + NeedSystem bool `json:"need_system"` + NeedCovers bool `json:"need_covers"` + Sizes bool `json:"sizes"` +} + +type AlbumPhotos struct { + OwnerID int `json:"owner_id"` + AlbumID any `json:"album_id"` + Type string `json:"type"` + PhotoIDs []int `json:"photo_ids"` + Rev bool `json:"rev"` + Extended bool `json:"extended"` + FeedType string `json:"feed_type"` + Feed int `json:"feed"` + Sizes bool `json:"sizes"` + Offset int `json:"offset"` + Count int `json:"count"` +} diff --git a/types/sendEventMessage.go b/types/sendEventMessage.go new file mode 100644 index 0000000..d826551 --- /dev/null +++ b/types/sendEventMessage.go @@ -0,0 +1,37 @@ +package types + +import "encoding/json" + +type SendMessageEventAnswer struct { + EventID string `json:"event_id"` + ChatID int `json:"peer_id"` + UserID int `json:"user_id"` + Action string `json:"action"` +} + +type EventAction struct { + Type string `json:"type,omitempty"` + + Text string `json:"text,omitempty"` // show_snackbar + Link string `json:"link,omitempty"` // open_link + + // open_app + AppID int `json:"app_id,omitempty"` + ApplicationID int `json:"-"` + OwnerID int `json:"owner_id,omitempty"` + Hash string `json:"hash,omitempty"` +} + +func (action EventAction) JSON() string { + var data []byte + + if action.Type == "open_app" && action.ApplicationID != 0 { + action.AppID = action.ApplicationID + } + + if marshal, err := json.Marshal(action); err == nil { + data = marshal + } + + return string(data) +} diff --git a/types/status.go b/types/status.go new file mode 100644 index 0000000..8143fad --- /dev/null +++ b/types/status.go @@ -0,0 +1,11 @@ +package types + +type GetStatus struct { + GroupID int `json:"group_id"` + UserID int `json:"user_id"` +} + +type SetStatus struct { + GroupID int `json:"group_id"` + Text string `json:"text"` +} diff --git a/types/upload.go b/types/upload.go new file mode 100644 index 0000000..803c802 --- /dev/null +++ b/types/upload.go @@ -0,0 +1,7 @@ +package types + +type UploadFile struct { + FieldName string + FileName string + Bytes []byte +} diff --git a/types/uploadMessagesDocumentServer.go b/types/uploadMessagesDocumentServer.go new file mode 100644 index 0000000..4ab7a00 --- /dev/null +++ b/types/uploadMessagesDocumentServer.go @@ -0,0 +1,10 @@ +package types + +type UploadMessagesPhotoServer struct { + ChatID int +} + +type UploadMessagesDocumentServer struct { + ChatID int + Type string +} diff --git a/types/users.go b/types/users.go new file mode 100644 index 0000000..8173f08 --- /dev/null +++ b/types/users.go @@ -0,0 +1,65 @@ +package types + +type User struct { + UserID int `json:"user_ids"` + UserIDs []int `json:"user_ids"` //nolint:govet + Fields []string `json:"fields"` + NameCase string `json:"name_case"` +} + +type Followers struct { + UserIDs []int `json:"user_ids"` + Offset int `json:"offset"` + Count int `json:"count"` + Fields []string `json:"fields"` + NameCase string `json:"name_case"` +} + +type Subscriptions struct { + UserID int `json:"user_id"` + Offset int `json:"offset"` + Count int `json:"count"` + Fields []string `json:"fields"` +} + +type ReportUser struct { + UserID int `json:"user_id"` + Type string `json:"type"` + Comment string `json:"comment"` +} + +type SearchUser struct { + Query string `json:"q"` + Sort int `json:"sort"` + Offset int `json:"offset"` + Count int `json:"count"` + Fields string `json:"fields"` + CityID int `json:"city"` + CountryID int `json:"country"` + Hometown int `json:"hometown"` + UniversityCountry int `json:"university_country"` + University int `json:"university"` + UniversityYear int `json:"university_year"` + UniversityFaculty int `json:"university_faculty"` + UniversityChair int `json:"university_chair"` + Gender int `json:"sex"` + Status int `json:"status"` + AgeFrom int `json:"age_from"` + AgeTo int `json:"age_to"` + BirthDay int `json:"birth_day"` + BirthMonth int `json:"birth_month"` + BirthYear int `json:"birth_year"` + Online int `json:"online"` + HasPhoto int `json:"has_photo"` + SchoolCountry int `json:"school_country"` + SchoolCity int `json:"school_city"` + SchoolClass int `json:"school_class"` + School int `json:"school"` + SchoolYear int `json:"school_year"` + Religion string `json:"religion"` + Company string `json:"company"` + Position string `json:"position"` + GroupID int `json:"group_id"` + FromList string `json:"from_list"` + ScreenRef string `json:"screen_ref"` +} diff --git a/update/action.go b/update/action.go new file mode 100644 index 0000000..830a976 --- /dev/null +++ b/update/action.go @@ -0,0 +1,15 @@ +package update + +type Action struct { + Type string `json:"type,omitempty"` + MemberID int `json:"member_id,omitempty"` + Text string `json:"text,omitempty"` + EMail string `json:"email,omitempty"` + Photo PhotoAction `json:"photo,omitempty"` +} + +type PhotoAction struct { + X50 string `json:"photo_50,omitempty"` + X100 string `json:"photo_100,omitempty"` + X200 string `json:"photo_200,omitempty"` +} diff --git a/update/appNotification.go b/update/appNotification.go new file mode 100644 index 0000000..5dee2d6 --- /dev/null +++ b/update/appNotification.go @@ -0,0 +1,8 @@ +package update + +type AppNotification struct { + UserID int `json:"user_id,omitempty"` + ID int `json:"app_id,omitempty"` + Payload string `json:"payload,omitempty"` + GroupID int `json:"group_id,omitempty"` +} diff --git a/update/attachment.go b/update/attachment.go new file mode 100644 index 0000000..2eadb8c --- /dev/null +++ b/update/attachment.go @@ -0,0 +1,10 @@ +package update + +type Attachment struct { + Type string `json:"type,omitempty"` + Photo AttachmentPhoto `json:"photo,omitempty"` + Document AttachmentDocument `json:"doc,omitempty"` + Video AttachmentVideo `json:"video,omitempty"` + Audio AttachmentAudio `json:"audio,omitempty"` + Market AttachmentMarket `json:"market,omitempty"` +} diff --git a/update/audio.go b/update/audio.go new file mode 100644 index 0000000..79ee1e4 --- /dev/null +++ b/update/audio.go @@ -0,0 +1,34 @@ +package update + +type AttachmentAudio Audio + +type Audio struct { + ID int `json:"id,omitempty"` + OwnerID int `json:"owner_id,omitempty"` + Artist string `json:"artist,omitempty"` + Title string `json:"title,omitempty"` + Duration int `json:"duration,omitempty"` + URL string `json:"url,omitempty"` + LyricsID int `json:"lyrics_id,omitempty"` + AlbumID int `json:"album_id,omitempty"` + GenreID int `json:"genre_id,omitempty"` + Date int `json:"date,omitempty"` + NoSearch int `json:"no_search,omitempty"` + IsHQ int `json:"is_hq,omitempty"` + + IsExplicit bool `json:"is_explicit,omitempty"` + IsFocusTrack bool `json:"is_focus_track,omitempty"` + TrackCode string `json:"track_code,omitempty"` + Artists []AudioArtist `json:"main_artists,omitempty"` + ShortVideosAllowed bool `json:"short_videos_allowed,omitempty"` + StoriesAllowed bool `json:"stories_allowed,omitempty"` + StoriesCoverAllowed bool `json:"stories_cover_allowed,omitempty"` +} + +type AudioArtist struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Domain string `json:"domain,omitempty"` + Followed bool `json:"is_followed,omitempty"` + CanFollow bool `json:"can_follow,omitempty"` +} diff --git a/update/block.go b/update/block.go new file mode 100644 index 0000000..08eb856 --- /dev/null +++ b/update/block.go @@ -0,0 +1,15 @@ +package update + +type BlockUser struct { + AdminID int `json:"admin_id,omitempty"` + UserID int `json:"user_id,omitempty"` + UnblockDate int `json:"unblock_date,omitempty"` + Reason int `json:"reason,omitempty"` + Comment string `json:"comment,omitempty"` +} + +type UnblockUser struct { + AdminID int `json:"admin_id,omitempty"` + UserID int `json:"user_id,omitempty"` + EndDate int `json:"by_end_date,omitempty"` +} diff --git a/update/board.go b/update/board.go new file mode 100644 index 0000000..71ae412 --- /dev/null +++ b/update/board.go @@ -0,0 +1,19 @@ +package update + +type BoardComment struct { + ID int `json:"id,omitempty"` + UserID int `json:"from_id,omitempty"` + Date int `json:"date,omitempty"` + Text string `json:"text,omitempty"` + Attachments []Attachment `json:"attachments,omitempty"` + Likes Likes `json:"likes,omitempty"` + + TopicID int `json:"topic_id,omitempty"` + TopicOwnerID int `json:"topic_owner_id,omitempty"` +} + +type DeleteBoardComment struct { + TopicOwnerID int `json:"topic_owner_id,omitempty"` + TopicID int `json:"topic_id,omitempty"` + ID int `json:"id,omitempty"` +} diff --git a/update/callback.go b/update/callback.go new file mode 100644 index 0000000..a217898 --- /dev/null +++ b/update/callback.go @@ -0,0 +1,10 @@ +package update + +type Callback struct { + ChatID int `json:"peer_id,omitempty"` + UserID int `json:"user_id,omitempty"` + EventID string `json:"event_id,omitempty"` + RawPayload rawPayload `json:"payload,omitempty"` + Payload map[string]string + ChatMessageID int `json:"conversation_message_id,omitempty"` +} diff --git a/update/clientInfo.go b/update/clientInfo.go new file mode 100644 index 0000000..a29952d --- /dev/null +++ b/update/clientInfo.go @@ -0,0 +1,9 @@ +package update + +type ClientInfo struct { + ButtonActions []string `json:"button_actions,omitempty"` + Keyboard bool `json:"keyboard,omitempty"` + InlineKeyboard bool `json:"inline_keyboard,omitempty"` + Carousel bool `json:"carousel,omitempty"` + LanguageID int `json:"lang_id,omitempty"` +} diff --git a/update/comments.go b/update/comments.go new file mode 100644 index 0000000..31e2c9b --- /dev/null +++ b/update/comments.go @@ -0,0 +1,9 @@ +package update + +type Comments struct { + Count int `json:"count,omitempty"` + CanPost int `json:"can_post,omitempty"` + GroupsCanPost bool `json:"groups_can_post,omitempty"` + CanClose bool `json:"can_close,omitempty"` + CanOpen bool `json:"can_open,omitempty"` +} diff --git a/update/community.go b/update/community.go new file mode 100644 index 0000000..c738b27 --- /dev/null +++ b/update/community.go @@ -0,0 +1,41 @@ +package update + +type EditOwners struct { + AdminID int `json:"admin_id,omitempty"` + UserID int `json:"user_id,omitempty"` + OldLevel int `json:"level_old,omitempty"` + NewLevel int `json:"level_new,omitempty"` +} + +type ControlGroup struct { + UserID int `json:"user_id,omitempty"` + Changes GroupChanges `json:"changes,omitempty"` +} + +type GroupChanges struct { + Topics GroupChange `json:"topics,omitempty"` + Photos GroupChange `json:"photos,omitempty"` + Videos GroupChange `json:"video,omitempty"` + Audios GroupChange `json:"audio,omitempty"` + Links GroupChange `json:"links,omitempty"` + Market GroupChange `json:"market,omitempty"` +} + +type GroupChange struct { + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + Access any `json:"access,omitempty"` + ScreenName string `json:"screen_name,omitempty"` + PublicCategory any `json:"public_caterogy,omitempty"` + PublicSubcategory any `json:"public_subcategory,omitempty"` + AgeLimits int `json:"age_limits,omitempty"` + Website string `json:"website,omitempty"` + EnablePhoto any `json:"enable_photo,omitempty"` + OldValue int `json:"old_value,omitempty"` + NewValue int `json:"new_value,omitempty"` +} + +type ChangeGroupPhoto struct { + UserID int `json:"user_id,omitempty"` + Photo AttachmentPhoto `json:"photo,omitempty"` +} diff --git a/update/copyright.go b/update/copyright.go new file mode 100644 index 0000000..d3ef173 --- /dev/null +++ b/update/copyright.go @@ -0,0 +1,8 @@ +package update + +type Copyright struct { + ID int `json:"id,omitempty"` + Link string `json:"link,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` +} diff --git a/update/document.go b/update/document.go new file mode 100644 index 0000000..17b095f --- /dev/null +++ b/update/document.go @@ -0,0 +1,37 @@ +package update + +type AttachmentDocument struct { + ID int `json:"id,omitempty"` + OwnerID int `json:"owner_id,omitempty"` + Title string `json:"title,omitempty"` + Size int `json:"size,omitempty"` + Extension string `json:"ext,omitempty"` + Date int `json:"date,omitempty"` + Type int `json:"type,omitempty"` + URL string `json:"url,omitempty"` + IsUnsafe int `json:"is_unsafe,omitempty"` + AccessKey string `json:"access_key,omitempty"` +} + +type PreviewDocument struct { + Photo PhotoDocument `json:"photo,omitempty"` + Video VideoDocument `json:"video,omitempty"` +} + +type PhotoDocument struct { + Sizes []PhotoDocumentSize `json:"sizes,omitempty"` +} + +type PhotoDocumentSize struct { + Type string `json:"type,omitempty"` + Source string `json:"src,omitempty"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` +} + +type VideoDocument struct { + Source string `json:"src,omitempty"` + FileSize string `json:"file_size,omitempty"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` +} diff --git a/update/donut.go b/update/donut.go new file mode 100644 index 0000000..3b9305f --- /dev/null +++ b/update/donut.go @@ -0,0 +1,28 @@ +package update + +type ProlongedDonate struct { + Amount int `json:"amount,omitempty"` + AmountWithoutFee float32 `json:"amount_without_fee,omitempty"` + UserID int `json:"user_id,omitempty"` +} + +type ExpiredDonate struct { + UserID int `json:"user_id,omitempty"` +} + +type ChangeDonatePrice struct { + OldAmount int `json:"amount_old,omitempty"` + NewAmount int `json:"amount_new,omitempty"` + AmountDiff float32 `json:"amount_diff,omitempty"` + AmountDiffWithoutFee float32 `json:"amount_diff_without_fee,omitempty"` + UserID int `json:"user_id,omitempty"` +} + +type WithdrawMoney struct { + Amount float32 `json:"amount,omitempty"` + AmountWithoutFee float32 `json:"amount_without_fee,omitempty"` +} + +type WithdrawMoneyError struct { + Reason string `json:"reason,omitempty"` +} diff --git a/update/geolocation.go b/update/geolocation.go new file mode 100644 index 0000000..49c6dde --- /dev/null +++ b/update/geolocation.go @@ -0,0 +1,24 @@ +package update + +type Geolocation struct { + Type string `json:"type,omitempty"` + Coordinates Coordinates `json:"coordinates,omitempty"` + Place Place `json:"place,omitempty"` + ShowMap string `json:"showmap,omitempty"` +} + +type Coordinates struct { + Latitude float64 `json:"latitude,omitempty"` + Longitude float64 `json:"longitude,omitempty"` +} + +type Place struct { + ID int `json:"id,omitempty"` + Title string `json:"title,omitempty"` + Latitude int `json:"latitude,omitempty"` + Longitude int `json:"longitude,omitempty"` + Created int `json:"created,omitempty"` + Icon string `json:"icon,omitempty"` + Country string `json:"country,omitempty"` + City string `json:"city,omitempty"` +} diff --git a/update/group.go b/update/group.go new file mode 100644 index 0000000..6e1a340 --- /dev/null +++ b/update/group.go @@ -0,0 +1,11 @@ +package update + +type JoinGroup struct { + UserID int `json:"user_id,omitempty"` + JoinType string `json:"join_type,omitempty"` +} + +type LeaveGroup struct { + UserID int `json:"user_id,omitempty"` + Self int `json:"self,omitempty"` +} diff --git a/update/likes.go b/update/likes.go new file mode 100644 index 0000000..7b018d5 --- /dev/null +++ b/update/likes.go @@ -0,0 +1,19 @@ +package update + +type Unlike Like + +type Like struct { + LikerID int `json:"liker_id,omitempty"` + ObjectType string `json:"object_type,omitempty"` + ObjectOwnerID int `json:"object_owner_id,omitempty"` + ThreadReplyID int `json:"thread_reply_id,omitempty"` + PostID int `json:"post_id,omitempty"` + ObjectID int `json:"object_id,omitempty"` +} + +type Likes struct { + Count int `json:"count,omitempty"` + Likes int `json:"user_likes,omitempty"` + CanLike int `json:"can_like,omitempty"` + CanPublish int `json:"can_publish,omitempty"` +} diff --git a/update/market.go b/update/market.go new file mode 100644 index 0000000..69252ed --- /dev/null +++ b/update/market.go @@ -0,0 +1,112 @@ +package update + +type MarketComment struct { + PostComment + + OwnerID int `json:"market_owner_id,omitempty"` + ItemID int `json:"item_id,omitempty"` +} + +type DeleteMarketComment struct { + OwnerID int `json:"owner_id,omitempty"` + ID int `json:"id,omitempty"` + UserID int `json:"user_id,omitempty"` + DeleterID int `json:"deleter_id,omitempty"` + ItemID int `json:"item_id,omitempty"` +} + +type OrderMarket struct { + ID int `json:"id,omitempty"` + GroupID int `json:"group_id,omitempty"` + UserID int `json:"user_id,omitempty"` + Date int `json:"date,omitempty"` + VariantsGroupingID int `json:"variants_grouping_id,omitempty"` + IsMainVariant bool `json:"is_main_variant,omitempty"` + PropertyValues []PropertyValues `json:"property_values,omitempty"` + CartQuantity int `json:"cart_quantity,omitempty"` + Status int `json:"status,omitempty"` + ItemsCount int `json:"items_count,omitempty"` + TotalPrice TotalPrice `json:"total_price,omitempty"` + DisplayOrderID string `json:"display_order_id,omitempty"` + Comment string `json:"comment,omitempty"` + PreviewOrderItems []AttachmentMarket `json:"preview_order_items,omitempty"` + Delivery OrderDelivery `json:"delivery,omitempty"` + Recipient Recipient `json:"recipient,omitempty"` +} + +type PropertyValues struct { + VariantID int `json:"variant_id,omitempty"` + VariantName string `json:"variant_name,omitempty"` + PropertyName string `json:"property_name,omitempty"` +} + +type TotalPrice struct { + Amount string `json:"amount,omitempty"` + Currency Currency `json:"currency,omitempty"` + Text string `json:"text,omitempty"` +} + +type OrderDelivery struct { + Address string `json:"address,omitempty"` + Type string `json:"type,omitempty"` + TrackNumber string `json:"track_number,omitempty"` + TrackLink string `json:"track_link,omitempty"` + DeliveryPoint any `json:"delivery_point,omitempty"` +} + +type Recipient struct { + Name string `json:"name,omitempty"` + Phone string `json:"phone,omitempty"` + DisplayText string `json:"display_text,omitempty"` +} + +type AttachmentMarket struct { + ID int `json:"id,omitempty"` + OwnerID int `json:"owner_id,omitempty"` + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + Price Price `json:"price,omitempty"` + Dimensions Dimensions `json:"dimensions,omitempty"` + Weight int `json:"weight,omitempty"` + Category Category `json:"category,omitempty"` + Cover string `json:"thumb_photo,omitempty"` + Date int `json:"date,omitempty"` + Access int `json:"availability,omitempty"` + IsFavorite bool `json:"is_favorite,omitempty"` + Vendor string `json:"sku,omitempty"` + Photos []AttachmentPhoto `json:"photos,omitempty"` + CanComment int `json:"can_comment,omitempty"` + CanRepost int `json:"can_repost,omitempty"` + Likes []Likes `json:"likes,omitempty"` + URL string `json:"url,omitempty"` + ButtonTitle string `json:"button_title,omitempty"` +} + +type Price struct { + Amount string `json:"amount,omitempty"` + Currency Currency `json:"currency,omitempty"` + UnDiscounted string `json:"old_amount,omitempty"` + Text string `json:"text,omitempty"` +} + +type Currency struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type Dimensions struct { + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` + Length int `json:"length,omitempty"` +} + +type Category struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Section Section `json:"section,omitempty"` +} + +type Section struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} diff --git a/update/message.go b/update/message.go new file mode 100644 index 0000000..15b8c61 --- /dev/null +++ b/update/message.go @@ -0,0 +1,66 @@ +package update + +import ( + "github.com/aejoy/vkgo/keyboard" +) + +type Message struct { + ID int `json:"id,omitempty"` + Date int `json:"date,omitempty"` + ChatID int `json:"peer_id,omitempty"` + UserID int `json:"from_id,omitempty"` + Text string `json:"text,omitempty"` + RandomID int `json:"random_id,omitempty"` + Referral string `json:"ref,omitempty"` + ReferralSource string `json:"ref_source,omitempty"` + Attachments []Attachment `json:"attachments,omitempty"` + Important bool `json:"important,omitempty"` + Geolocation Geolocation `json:"geo,omitempty"` + RawPayload rawPayload `json:"payload,omitempty"` + Payload map[string]string + Keyboard keyboard.Keyboard `json:"keyboard,omitempty"` + Forwards []*Message `json:"fwd_messages,omitempty"` + Reply *Message `json:"reply_message,omitempty"` + Action Action `json:"action,omitempty"` + AuthorID int `json:"admin_author_id,omitempty"` + ChatMessageID int `json:"conversation_message_id,omitempty"` + Cropped bool `json:"is_cropped,omitempty"` + MembersCount int `json:"members_count,omitempty"` + UpdateTime int `json:"update_time,omitempty"` + Listened bool `json:"was_listened,omitempty"` + PinnedAt int `json:"pinned_at,omitempty"` + Tag string `json:"message_tag,omitempty"` + Out int `json:"out,omitempty"` + Hidden bool `json:"is_hidden,omitempty"` + ExpireTime int `json:"expire_ttl"` + + // without documentation + Version int `json:"version,omitempty"` +} + +type EnableMessage struct { + UserID int `json:"user_id,omitempty"` + Key string `json:"key,omitempty"` +} + +type DisableMessage struct { + UserID int `json:"user_id,omitempty"` +} + +type Typing struct { + State string `json:"state,omitempty"` + UserID int `json:"from_id,omitempty"` + ToID int `json:"to_id,omitempty"` +} + +type forwardsMain func(*Message, int) + +func (message Message) ForEachForwards(execute forwardsMain) { + for index, message := range message.Forwards { + execute(message, index) + } + + if message.Reply != nil { + execute(message.Reply, len(message.Forwards)) + } +} diff --git a/update/object.go b/update/object.go new file mode 100644 index 0000000..d38d10b --- /dev/null +++ b/update/object.go @@ -0,0 +1,6 @@ +package update + +type Object struct { + Message Message `json:"message,omitempty"` + ClientInfo ClientInfo `json:"client_info,omitempty"` +} diff --git a/update/payload.go b/update/payload.go new file mode 100644 index 0000000..2a837bf --- /dev/null +++ b/update/payload.go @@ -0,0 +1,46 @@ +package update + +import ( + "encoding/json" + "fmt" +) + +type rawPayload any + +func DecodePayload(rawPayload rawPayload) (map[string]string, error) { + payload := map[string]string{} + + switch rp := rawPayload.(type) { + case string: + object := map[string]any{} + + if err := json.Unmarshal([]byte(rp), &object); err != nil { + return payload, err + } + + for name, value := range object { + payload[name] = fmt.Sprintf("%v", value) + } + + return payload, nil + case map[string]any: + var ( + object = map[string]any{} + body, err = json.Marshal(rp) + ) + + if err != nil { + return payload, err + } + + if err := json.Unmarshal(body, &object); err != nil { + return payload, err + } + + for name, value := range object { + payload[name] = fmt.Sprintf("%v", value) + } + } + + return payload, nil +} diff --git a/update/photo.go b/update/photo.go new file mode 100644 index 0000000..dca5bcd --- /dev/null +++ b/update/photo.go @@ -0,0 +1,41 @@ +package update + +type AttachmentPhoto Photo + +type Photo struct { + AlbumID int `json:"album_id,omitempty"` + Date int `json:"date,omitempty"` + ID int `json:"id,omitempty"` + OwnerID int `json:"owner_id,omitempty"` + UserID int `json:"user_id,omitempty"` + CanComment int `json:"can_comment,omitempty"` + PostID int `json:"post_id,omitempty"` + Sizes []PhotoSize `json:"sizes,omitempty"` + Text string `json:"text,omitempty"` + WebViewToken string `json:"web_view_token,omitempty"` + Likes Likes `json:"likes,omitempty"` + Comments Comments `json:"comments,omitempty"` + Reposts Reposts `json:"reposts,omitempty"` + Tags Tags `json:"tags,omitempty"` + OriginalPhoto PhotoSize `json:"orig_photo,omitempty"` + CanRepost int `json:"can_repost"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` + SquareCrop string `json:"square_crop,omitempty"` + HasTags bool `json:"has_tags,omitempty"` +} + +type PhotoSize struct { + Type string `json:"type,omitempty"` + URL string `json:"url,omitempty"` + SourceURL string `json:"src,omitempty"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` +} + +type PhotoComment struct { + PostComment + + PhotoID int `json:"photo_id,omitempty"` + PhotoOwnerID int `json:"photo_owner_id,omitempty"` +} diff --git a/update/post.go b/update/post.go new file mode 100644 index 0000000..5b17841 --- /dev/null +++ b/update/post.go @@ -0,0 +1,64 @@ +package update + +type Post struct { + ID int `json:"id,omitempty"` + OwnerID int `json:"owner_id,omitempty"` + UserID int `json:"from_id,omitempty"` + CreatedBy int `json:"created_by,omitempty"` + Date int `json:"date,omitempty"` + Text string `json:"text,omitempty"` + ReplyOwnerID int `json:"reply_owner_id,omitempty"` + ReplyPostID int `json:"reply_post_id,omitempty"` + FriendsOnly int `json:"friends_only,omitempty"` + Comments Comments `json:"comments,omitempty"` + Copyright Copyright `json:"copyright,omitempty"` + Likes Likes `json:"likes,omitempty"` + Reposts Reposts `json:"reposts,omitempty"` + Views Views `json:"views,omitempty"` + Type string `json:"post_type,omitempty"` + Source string `json:"post_source,omitempty"` + Attachments []Attachment `json:"attachments,omitempty"` + Geolocation Geolocation `json:"geo,omitempty"` + SignerID int `json:"signer_id,omitempty"` + CopyHistory []any `json:"copy_history,omitempty"` + CanPin int `json:"can_pin,omitempty"` + CanDelete int `json:"can_delete,omitempty"` + CanEdit int `json:"can_edit,omitempty"` + Pinned int `json:"is_pinned,omitempty"` + MarkedAsAds int `json:"marked_as_ads,omitempty"` + IsFavorite bool `json:"is_favorite,omitempty"` + Donut struct { + IsDonut bool `json:"is_donut,omitempty"` + PaidDuration int `json:"paid_duration,omitempty"` + Placeholder any `json:"placeholder,omitempty"` + CanPublishFreeCopy bool `json:"can_publish_free_copy,omitempty"` + EditMode string `json:"edit_mode,omitempty"` + } `json:"donut,omitempty"` + PostponedID int `json:"postponed_id,omitempty"` +} + +type PostComment struct { + ID int `json:"id,omitempty"` + UserID int `json:"from_id,omitempty"` + Date int `json:"date,omitempty"` + Text string `json:"text,omitempty"` + Donut struct { + IsDon bool `json:"is_don,omitempty"` + Placeholder string `json:"placeholder,omitempty"` + } `json:"donut,omitempty"` + ReplyToUser int `json:"reply_to_user,omitempty"` + ReplyToComment int `json:"reply_to_comment,omitempty"` + Attachments []Attachment `json:"attachments,omitempty"` + ParentsStack []int `json:"parents_stack,omitempty"` + Thread Thread `json:"thread,omitempty"` + + PostID int `json:"post_id,omitempty"` + PostOwnerID int `json:"post_owner_id,omitempty"` +} + +type DeletePostComment struct { + OwnerID int `json:"owner_id,omitempty"` + ID int `json:"id,omitempty"` + DeleterID int `json:"deleter_id,omitempty"` + PostID int `json:"post_id,omitempty"` +} diff --git a/update/reposts.go b/update/reposts.go new file mode 100644 index 0000000..41d4912 --- /dev/null +++ b/update/reposts.go @@ -0,0 +1,8 @@ +package update + +type Reposts struct { + Count int `json:"count,omitempty"` + Posts int `json:"wall_count,omitempty"` + MessagesCount int `json:"mail_count,omitempty"` + Reposted int `json:"user_reposted,omitempty"` +} diff --git a/update/tags.go b/update/tags.go new file mode 100644 index 0000000..94488bb --- /dev/null +++ b/update/tags.go @@ -0,0 +1,5 @@ +package update + +type Tags struct { + Count int `json:"count,omitempty"` +} diff --git a/update/thread.go b/update/thread.go new file mode 100644 index 0000000..04559a3 --- /dev/null +++ b/update/thread.go @@ -0,0 +1,9 @@ +package update + +type Thread struct { + Count int `json:"count,omitempty"` + Items []any `json:"items,omitempty"` + CanPost bool `json:"can_post,omitempty"` + ShowReplyButton bool `json:"show_reply_button,omitempty"` + GroupsCanPost bool `json:"groups_can_post,omitempty"` +} diff --git a/update/update.go b/update/update.go new file mode 100644 index 0000000..a6f5082 --- /dev/null +++ b/update/update.go @@ -0,0 +1,19 @@ +package update + +import "encoding/json" + +type Updates struct { + TS any `json:"ts,omitempty"` + Updates []Update `json:"updates,omitempty"` + Failed int `json:"failed,omitempty"` + MinVersion int `json:"min_version,omitempty"` + MaxVersion int `json:"max_version,omitempty"` +} + +type Update struct { + GroupID int `json:"group_id,omitempty"` + Type string `json:"type,omitempty"` + EventID string `json:"event_id,omitempty"` + Version string `json:"v,omitempty"` + Object json.RawMessage `json:"object,omitempty"` +} diff --git a/update/video.go b/update/video.go new file mode 100644 index 0000000..189dce7 --- /dev/null +++ b/update/video.go @@ -0,0 +1,69 @@ +package update + +type AttachmentVideo Video + +type Video struct { + ID int `json:"id,omitempty"` + OwnerID int `json:"owner_id,omitempty"` + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + Duration int `json:"duration,omitempty"` + Photos []VideoPhoto `json:"image,omitempty"` + FirstFrame []VideoPhoto `json:"first_frame,omitempty"` + Date int `json:"date,omitempty"` + AddingDate int `json:"adding_date,omitempty"` + Views int `json:"views,omitempty"` + LocalViews int `json:"local_views,omitempty"` + Comments int `json:"comments,omitempty"` + Player string `json:"player,omitempty"` + Platform string `json:"platform,omitempty"` + CanAdd int `json:"can_add,omitempty"` + IsPrivate int `json:"is_private,omitempty"` + AccessKey string `json:"access_key,omitempty"` + Processing int `json:"processing,omitempty"` + IsFavorite bool `json:"is_favorite,omitempty"` + CanComment int `json:"can_comment,omitempty"` + CanEdit int `json:"can_edit,omitempty"` + CanLike int `json:"can_like,omitempty"` + CanRepost int `json:"can_repost,omitempty"` + CanSubscribe int `json:"can_subscribe,omitempty"` + CanAddToFaves int `json:"can_add_to_faves,omitempty"` + CanAttachLink int `json:"can_attach_link,omitempty"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` + UserID int `json:"user_id,omitempty"` + Converting int `json:"converting,omitempty"` + Added int `json:"added,omitempty"` + Subscribed int `json:"is_subscribed,omitempty"` + Repeat int `json:"repeat,omitempty"` + Type string `json:"type,omitempty"` + Balance int `json:"balance,omitempty"` + LiveStatus string `json:"live_status,omitempty"` + Live int `json:"live,omitempty"` + Upcoming int `json:"upcoming,omitempty"` + Spectators int `json:"spectators,omitempty"` + Likes Likes `json:"likes,omitempty"` + Reposts Reposts `json:"reposts,omitempty"` +} + +type VideoPhoto struct { + URL string `json:"url,omitempty"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` + WithPadding int `json:"with_padding,omitempty"` +} + +type VideoComment struct { + PostComment + + VideoID int `json:"video_id,omitempty"` + VideoOwnerID int `json:"video_owner_id"` +} + +type DeleteVideoComment struct { + OwnerID int `json:"owner_id,omitempty"` + ID int `json:"id,omitempty"` + UserID int `json:"user_id,omitempty"` + DeleterID int `json:"deleter_id,omitempty"` + VideoID int `json:"ideo_id,omitempty"` +} diff --git a/update/views.go b/update/views.go new file mode 100644 index 0000000..1a5e952 --- /dev/null +++ b/update/views.go @@ -0,0 +1,5 @@ +package update + +type Views struct { + Count int `json:"count,omitempty"` +} diff --git a/update/vkPay.go b/update/vkPay.go new file mode 100644 index 0000000..5888a88 --- /dev/null +++ b/update/vkPay.go @@ -0,0 +1,8 @@ +package update + +type VKPayTransaction struct { + UserID int `json:"from_id,omitempty"` + Amount int `json:"amount,omitempty"` + Description string `json:"description,omitempty"` + Date int `json:"date,omitempty"` +} diff --git a/update/vote.go b/update/vote.go new file mode 100644 index 0000000..3b0c61d --- /dev/null +++ b/update/vote.go @@ -0,0 +1,8 @@ +package update + +type Vote struct { + OwnerID int `json:"owner_id,omitempty"` + PollID int `json:"poll_id,omitempty"` + OptionID int `json:"option_id,omitempty"` + UserID int `json:"user_id,omitempty"` +} diff --git a/utils/files.go b/utils/files.go new file mode 100644 index 0000000..6e40092 --- /dev/null +++ b/utils/files.go @@ -0,0 +1,32 @@ +package utils + +import ( + "context" + "io" + "net/http" +) + +func GetFileFromURL(url string) (data []byte, err error) { + request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, nil) + if err != nil { + return nil, err + } + + response, err := http.DefaultClient.Do(request) + if err != nil { + return nil, err + } + + body, err := io.ReadAll(response.Body) + if err != nil { + return nil, err + } + + data = body + + if err = response.Body.Close(); err != nil { + return nil, err + } + + return +}