{"action":"created","issue":{"url":"https://api.github.com/repos/PokemonGoF/PokemonGo-Bot/issues/3672","repository_url":"https://api.github.com/repos/PokemonGoF/PokemonGo-Bot","labels_url":"https://api.github.com/repos/PokemonGoF/PokemonGo-Bot/issues/3672/labels{/name}","comments_url":"https://api.github.com/repos/PokemonGoF/PokemonGo-Bot/issues/3672/comments","events_url":"https://api.github.com/repos/PokemonGoF/PokemonGo-Bot/issues/3672/events","html_url":"https://github.com/PokemonGoF/PokemonGo-Bot/issues/3672","id":170787620,"number":3672,"title":"Proposal: Utilizing Public Sniping Lists","user":{"login":"TheSavior","id":249164,"avatar_url":"https://avatars.githubusercontent.com/u/249164?v=3","gravatar_id":"","url":"https://api.github.com/users/TheSavior","html_url":"https://github.com/TheSavior","followers_url":"https://api.github.com/users/TheSavior/followers","following_url":"https://api.github.com/users/TheSavior/following{/other_user}","gists_url":"https://api.github.com/users/TheSavior/gists{/gist_id}","starred_url":"https://api.github.com/users/TheSavior/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TheSavior/subscriptions","organizations_url":"https://api.github.com/users/TheSavior/orgs","repos_url":"https://api.github.com/users/TheSavior/repos","events_url":"https://api.github.com/users/TheSavior/events{/privacy}","received_events_url":"https://api.github.com/users/TheSavior/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/PokemonGoF/PokemonGo-Bot/labels/enhancement","name":"enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/PokemonGoF/PokemonGo-Bot/labels/help%20wanted","name":"help wanted","color":"128A0C"},{"url":"https://api.github.com/repos/PokemonGoF/PokemonGo-Bot/labels/new%20feature","name":"new feature","color":"bfd4f2"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":14,"created_at":"2016-08-12T02:29:30Z","updated_at":"2016-08-13T01:02:28Z","closed_at":null,"body":"# Utilizing Sniping Lists\r\nThere are a bunch of services right now that provide lists of pokemon that are live, and snipeable. Examples include:\r\n\r\n - [PokeSnipers](http://pokesnipers.com/)\r\n - [Pokezz](http://pokezz.com/)\r\n - [PokeWatchers](https://pokewatchers.com/)\r\n - [Haxton](http://haxton.io/api/pokemon)\r\n - [Skiplagged](https://skiplagged.com/pokemon)\r\n - and many more\r\n\r\nWe want to be able to allow our bots to support sniping from these lists. Each site has a different way to read data from their api. \r\n\r\n## Requirements for a valid solution:\r\n - The user of the bot must be able to configure which list(s) they want to pull from\r\n - The user must be able to configure which pokemon they want to snipe\r\n - Different websites have different data formats and needs (only sending VIPs or perfect IVs for example)\r\n - Creating a new data source should be possible using plugins\r\n - We must be able to report found pokemon back to the configured servers.\r\n\r\n## Solution:\r\n\r\n### Example Configuration\r\nI imagine the configuration for this task to be something like this:\r\n```\r\n{\r\n  // ...\r\n  \"tasks\": [\r\n    {\r\n      \"type\": \"SnipePokemon\",\r\n      \"config\": {\r\n        \"providers\": [\r\n          \"PokeSnipers\",\r\n          \"Haxton\"\r\n        ]\r\n      }\r\n    },\r\n  ],\r\n  \"catch\": {\r\n    \"Growlith\": { \"catch_above_cp\": 1000, \"catch_above_iv\": 0.95, \"logic\": \"or\" }\r\n  },\r\n  \"vips\" : {\r\n    \"Dragonite\": {},\r\n    \"Snorlax\": {}\r\n  }\r\n  // ...\r\n}\r\n```\r\n\r\n### Providers\r\nIn this solution I will use the term `Provider` to mean a python class that provides the data from a single source.\r\n\r\nThere will be a `SnipingProviderBase` class that providers can implement. Here is a sample implementation:\r\n\r\n```python\r\nclass SnipingProviderBase(object):\r\n  def initialize(self):\r\n    self.search_config = self.config.get('search_config', {})\r\n\r\n  def encountered_pokemon(self, pokemon):\r\n    \"\"\"\r\n    format the pokemon and send the data to the server\r\n    \"\"\"\r\n    pass\r\n\r\n  def search_for_pokemon(self):\r\n    \"\"\"\r\n    connect to the provider, possibly using search_config with the provider api\r\n    return a list of pokemon location objects\r\n    \"\"\"\r\n    pass\r\n```\r\n\r\nAnd then for an idea of what the `SnipePokemon` task might look something like this:\r\n\r\n```python\r\nclass SnipingTask(BaseTask):\r\n  def initialize(self):\r\n    self.raw_providers = self.config.get('providers', []);\r\n    self.search_config = self.config.get('search_config', {})\r\n\r\n    self.providers = [\r\n      # Class references to instantiated providers\r\n    ]\r\n\r\n    # self.bot.event_manager.add_handler(...\r\n    # register an event listener that listens for \r\n    # encounter pokemon and sends it to all providers\r\n\r\n  def encountered_pokemon(self, data):\r\n    for provider in self.providers:\r\n      provider.encountered_pokemon(data)\r\n\r\n  def work(self):\r\n    # create a merged list of pokemon from all the providers\r\n    # filter by search_config\r\n    # sort\r\n    # snipe\r\n    pass\r\n```\r\n\r\nI imagine a real solution would be more complicated to have more caching and not need to make a request to the provider on every tick. Since we will have a list of pokemon waiting for us that just needs to be refreshed.\r\n\r\n### Keeping track of what has already been caught\r\nIf each provider is returning a list of the pokemon that match the configuration, and we cache that list so we don't make a request every tick, then when we catch pokemon, we need to be able to make sure we ignore the pokemon we have already caught. We can do this by having the `SnipingTask` keep a list of the pokemon it has already caught. On every tick we will remove from that list every pokemon that would no longer be visible. Then, when we get the lists from all of the providers, we can remove all of the ones in our already_caught list. This means we need some unique ID per sighting. If there is no unique ID provided by the api, we can create a hash of the object.\r\n\r\n## Plugins\r\nWe [currently support plugins for tasks](https://github.com/PokemonGoF/PokemonGo-Bot/blob/master/docs/plugins.md), and anything we do for sniping providers should work with that same base. \r\n\r\nBy specifying in the config as an array of class names of providers, the SnipingTask can work very similarly to the [way we create the list of tasks](https://github.com/PokemonGoF/PokemonGo-Bot/blob/master/pokemongo_bot/tree_config_builder.py). \r\n\r\n## Future Directions\r\nBy making it possible to create sniping providers as plugins, and as easily configurable as our bot currently is, I could imagine a significant amount of the projects on the web that work to gather pokemon data actually being able to be built on top of this. Imagine this configuration:\r\n\r\n```\r\n\"tasks\": [\r\n  {\r\n    \"type\": \"SnipePokemon\",\r\n    \"config\": {\r\n      \"providers\": [\r\n        \"my_plugin.MyCoolPokemonMapSite\"\r\n      ],\r\n      \"catch_vips\": false,\r\n      \"catch\": {}\r\n    }\r\n  },\r\n  {\r\n    \"type\": \"FollowSpiral\",\r\n    \"config\": {\r\n      \"diameter\": 4,\r\n      \"step_size\": 70\r\n    }\r\n  }\r\n]\r\n```\r\n\r\nWith no other configuration, the bot would do nothing except walk in a spiral and report the pokemon it finds to the configured server. Neat!\r\n"},"comment":{"url":"https://api.github.com/repos/PokemonGoF/PokemonGo-Bot/issues/comments/239592303","html_url":"https://github.com/PokemonGoF/PokemonGo-Bot/issues/3672#issuecomment-239592303","issue_url":"https://api.github.com/repos/PokemonGoF/PokemonGo-Bot/issues/3672","id":239592303,"user":{"login":"EnvisageX","id":21001247,"avatar_url":"https://avatars.githubusercontent.com/u/21001247?v=3","gravatar_id":"","url":"https://api.github.com/users/EnvisageX","html_url":"https://github.com/EnvisageX","followers_url":"https://api.github.com/users/EnvisageX/followers","following_url":"https://api.github.com/users/EnvisageX/following{/other_user}","gists_url":"https://api.github.com/users/EnvisageX/gists{/gist_id}","starred_url":"https://api.github.com/users/EnvisageX/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EnvisageX/subscriptions","organizations_url":"https://api.github.com/users/EnvisageX/orgs","repos_url":"https://api.github.com/users/EnvisageX/repos","events_url":"https://api.github.com/users/EnvisageX/events{/privacy}","received_events_url":"https://api.github.com/users/EnvisageX/received_events","type":"User","site_admin":false},"created_at":"2016-08-13T01:02:28Z","updated_at":"2016-08-13T01:02:28Z","body":"I wasn't sniping last night... still got the 2 accounts I was running banned. So please write this feature. :)"}}
{"actor":{"display_login":"EnvisageX"}}