master
commit
bbcb88cdcc
|
@ -0,0 +1,10 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{ex,exs,yml}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
|
@ -0,0 +1,20 @@
|
|||
# The directory Mix will write compiled artifacts to.
|
||||
/_build
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps
|
||||
|
||||
# Where 3rd-party dependencies like ExDoc output generated docs.
|
||||
/doc
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
|
@ -0,0 +1,17 @@
|
|||
language: elixir
|
||||
elixir:
|
||||
- 1.3.0
|
||||
otp_release:
|
||||
- 19.0
|
||||
- 18.0
|
||||
sudo: false
|
||||
notifications:
|
||||
recipients:
|
||||
- milmazz@gmail.com
|
||||
env:
|
||||
- MIX_ENV=test
|
||||
script:
|
||||
- "mix do local.hex --force, deps.get, test"
|
||||
cache:
|
||||
directories:
|
||||
- deps
|
|
@ -0,0 +1,13 @@
|
|||
Copyright 2017 Milton Mazzarri
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,166 @@
|
|||
# Hunter (alpha)
|
||||
|
||||
A Elixir client for [Mastodon](https://github.com/Gargron/mastodon/), a GNU social-compatible micro-blogging service
|
||||
|
||||
## Installation
|
||||
|
||||
```elixir
|
||||
def deps do
|
||||
[{:hunter, "~> 0.1.0"}]
|
||||
end
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Assumming that you already know your *instance* and your *bearer token* you can do
|
||||
the following:
|
||||
|
||||
```elixir
|
||||
iex(1)> conn = Hunter.new([base_url: "https://example.com", bearer_token: "123456"])
|
||||
%Hunter.Client{base_url: "https://example.com",
|
||||
bearer_token: "123456"}
|
||||
```
|
||||
|
||||
### Getting the current user
|
||||
|
||||
```elixir
|
||||
iex(2)> Hunter.verify_credentials(conn)
|
||||
%Hunter.Account{acct: "milmazz",
|
||||
avatar: "https://social.lou.lt/avatars/original/missing.png",
|
||||
created_at: "2017-04-06T17:43:55.325Z", display_name: "Milton Mazzarri",
|
||||
followers_count: 2, following_count: 3,
|
||||
header: "https://social.lou.lt/headers/original/missing.png", id: 8039,
|
||||
locked: false, note: "", statuses_count: 1,
|
||||
url: "https://social.lou.lt/@milmazz", username: "milmazz"}
|
||||
```
|
||||
|
||||
### Fetching an account
|
||||
|
||||
```elixir
|
||||
iex(3)> Hunter.account(conn, 8039)
|
||||
%Hunter.Account{acct: "milmazz",
|
||||
avatar: "https://social.lou.lt/avatars/original/missing.png",
|
||||
created_at: "2017-04-06T17:43:55.325Z", display_name: "Milton Mazzarri",
|
||||
followers_count: 2, following_count: 3,
|
||||
header: "https://social.lou.lt/headers/original/missing.png", id: 8039,
|
||||
locked: false, note: "", statuses_count: 1,
|
||||
url: "https://social.lou.lt/@milmazz", username: "milmazz"}
|
||||
```
|
||||
|
||||
### Getting an account's followers
|
||||
|
||||
Returns a list of `Accounts`
|
||||
|
||||
```elixir
|
||||
iex(4)> Hunter.followers(conn, 8039)
|
||||
[%Hunter.Account{acct: "atmantree@mastodon.club",
|
||||
avatar: "https://social.lou.lt/system/accounts/avatars/000/008/518/original/7715529d4ceb4554.jpg?1491509276",
|
||||
created_at: "2017-04-06T20:07:57.119Z", display_name: "Carlos Gustavo Ruiz",
|
||||
followers_count: 2, following_count: 2,
|
||||
header: "https://social.lou.lt/system/accounts/headers/000/008/518/original/394f31473de7c64a.png?1491509277",
|
||||
id: 8518, locked: false,
|
||||
note: "Programmer, Pythonista, Web Creature, Blogger, C++ and Haskell Fan. Never stop learning, because life never stops teaching.",
|
||||
statuses_count: 1, url: "https://mastodon.club/@atmantree",
|
||||
username: "atmantree"},
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
### Getting who account is following
|
||||
|
||||
Returns a list of `Accounts`
|
||||
|
||||
```elixir
|
||||
iex(5)> Hunter.following(conn, 8039)
|
||||
[%Hunter.Account{acct: "sebasmagri@mastodon.cloud",
|
||||
avatar: "https://social.lou.lt/system/accounts/avatars/000/007/899/original/19b4d8c1e9d4e68a.jpg?1491498458",
|
||||
created_at: "2017-04-06T17:07:38.912Z",
|
||||
display_name: "Sebastián Ramírez Magrí", followers_count: 2,
|
||||
following_count: 1,
|
||||
header: "https://social.lou.lt/system/accounts/headers/000/007/899/original/missing.png?1491498458",
|
||||
id: 7899, locked: false, note: "", statuses_count: 2,
|
||||
url: "https://mastodon.cloud/@sebasmagri", username: "sebasmagri"},
|
||||
...]
|
||||
```
|
||||
|
||||
### Following a remote user
|
||||
|
||||
```elixir
|
||||
iex(6)> Hunter.follow_by_uri(conn, "paperswelove@mstdn.io")
|
||||
%Hunter.Account{acct: "paperswelove@mstdn.io",
|
||||
avatar: "https://social.lou.lt/system/accounts/avatars/000/007/126/original/60ecc8225809c008.png?1491486258",
|
||||
created_at: "2017-04-06T13:44:18.281Z", display_name: "Papers We Love",
|
||||
followers_count: 1, following_count: 0,
|
||||
header: "https://social.lou.lt/system/accounts/headers/000/007/126/original/missing.png?1491486258",
|
||||
id: 7126, locked: false,
|
||||
note: "Building Bridges Between Academia and Industry\r\n\r\n<a href=\"http://paperswelove.org\" rel=\"nofollow noopener\"><span class=\"invisible\">http://</span><span class=\"\">paperswelove.org</span><span class=\"invisible\"></span></a>\r\n<a href=\"http://pwlconf.org\" rel=\"nofollow noopener noopener\"><span class=\"invisible\">http://</span><span class=\"\">pwlconf.org</span><span class=\"invisible\"></span></a>",
|
||||
statuses_count: 1, url: "https://mstdn.io/@paperswelove",
|
||||
username: "paperswelove"}
|
||||
```
|
||||
|
||||
### Muting/unmuting an account
|
||||
|
||||
```elixir
|
||||
iex(7)> Hunter.mute(conn, 7899)
|
||||
%Hunter.Relationship{blocking: false, followed_by: false, following: true,
|
||||
muting: true, requested: false}
|
||||
iex(8)> Hunter.unmute(conn, 7899)
|
||||
%Hunter.Relationship{blocking: false, followed_by: false, following: true,
|
||||
muting: false, requested: false}
|
||||
```
|
||||
|
||||
### Getting an account's statuses
|
||||
|
||||
```elixir
|
||||
iex(9)> Hunter.statuses(conn, 8039, [limit: 1])
|
||||
[%Hunter.Status{account: %{"acct" => "milmazz",
|
||||
"avatar" => "https://social.lou.lt/avatars/original/missing.png",
|
||||
"created_at" => "2017-04-06T17:43:55.325Z",
|
||||
"display_name" => "Milton Mazzarri", "followers_count" => 2,
|
||||
"following_count" => 4,
|
||||
"header" => "https://social.lou.lt/headers/original/missing.png",
|
||||
"id" => 8039, "locked" => false, "note" => "", "statuses_count" => 1,
|
||||
"url" => "https://social.lou.lt/@milmazz", "username" => "milmazz"},
|
||||
application: %{"name" => "Web", "website" => nil},
|
||||
content: "<p><a href=\"http://tootplanet.space/@Shutsumon\" class=\"h-card u-url p-nickname mention\">@<span>Shutsumon</span></a> You should read "How to design programs" book <a href=\"http://htdp.org\" rel=\"nofollow noopener\" target=\"_blank\"><span class=\"invisible\">http://</span><span class=\"\">htdp.org</span><span class=\"invisible\"></span></a></p>",
|
||||
created_at: "2017-04-06T18:28:59.392Z", favourited: nil, favourites_count: 0,
|
||||
id: 59144, in_reply_to_account_id: 7742, in_reply_to_id: 59042,
|
||||
media_attachments: [],
|
||||
mentions: [%{"acct" => "Shutsumon@tootplanet.space", "id" => 7742,
|
||||
"url" => "http://tootplanet.space/@Shutsumon", "username" => "Shutsumon"}],
|
||||
reblog: nil, reblogged: nil, reblogs_count: 0, sensitive: false,
|
||||
spoiler_text: "", tags: [],
|
||||
uri: "tag:social.lou.lt,2017-04-06:objectId=59144:objectType=Status",
|
||||
url: "https://social.lou.lt/@milmazz/59144", visibility: "public"}]
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
||||
* OAuth2 authentication
|
||||
- Register client for token-access
|
||||
- Token authentication for API usage
|
||||
* Search for accounts or content
|
||||
* Getting an account's relationship
|
||||
* Register an application
|
||||
* Fetching a user's blocks
|
||||
* Fetching a user's favourites
|
||||
* Fetching a list of follow requests
|
||||
* Authorizing or rejecting follow requests
|
||||
* Support arrays as parameter types
|
||||
* Getting instance information
|
||||
* Uploading media attachment
|
||||
* Fetching a user's mutes
|
||||
* Fetching a user's notifications
|
||||
* Getting a single notification
|
||||
* Clearing notifications
|
||||
* Fetching user's reports
|
||||
* Reporting a user
|
||||
* Getting status context
|
||||
* Getting a card associated with a status
|
||||
* Getting who reblogged/favourited a status
|
||||
|
||||
## License
|
||||
|
||||
Hunter source code is released under Apache 2 License.
|
||||
|
||||
Check the [LICENSE](LICENSE) for more information.
|
|
@ -0,0 +1,30 @@
|
|||
# This file is responsible for configuring your application
|
||||
# and its dependencies with the aid of the Mix.Config module.
|
||||
use Mix.Config
|
||||
|
||||
# This configuration is loaded before any dependency and is restricted
|
||||
# to this project. If another project depends on this project, this
|
||||
# file won't be loaded nor affect the parent project. For this reason,
|
||||
# if you want to provide default values for your application for
|
||||
# 3rd-party users, it should be done in your "mix.exs" file.
|
||||
|
||||
# You can configure for your application as:
|
||||
#
|
||||
# config :hunter, key: :value
|
||||
#
|
||||
# And access this configuration in your application as:
|
||||
#
|
||||
# Application.get_env(:hunter, :key)
|
||||
#
|
||||
# Or configure a 3rd-party app:
|
||||
#
|
||||
# config :logger, level: :info
|
||||
#
|
||||
|
||||
# It is also possible to import configuration files, relative to this
|
||||
# directory. For example, you can emulate configuration per environment
|
||||
# by uncommenting the line below and defining dev.exs, test.exs and such.
|
||||
# Configuration from the imported file will override the ones defined
|
||||
# here (which is why it is important to import them last).
|
||||
#
|
||||
import_config "#{Mix.env}.exs"
|
|
@ -0,0 +1,3 @@
|
|||
use Mix.Config
|
||||
|
||||
config :hunter, hunter_api: Hunter.Api.HTTPClient
|
|
@ -0,0 +1,3 @@
|
|||
use Mix.Config
|
||||
|
||||
config :hunter, hunter_api: Hunter.Api.InMemory
|
|
@ -0,0 +1,384 @@
|
|||
defmodule Hunter do
|
||||
@moduledoc """
|
||||
A Elixir client for Mastodon, a GNU Social compatible micro-blogging service
|
||||
|
||||
"""
|
||||
|
||||
@hunter_version Mix.Project.config[:version]
|
||||
|
||||
@doc """
|
||||
Retrieve account of authenticated user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
|
||||
"""
|
||||
@spec verify_credentials(Hunter.Client.t) :: Hunter.Account.t
|
||||
def verify_credentials(conn), do: Hunter.Account.verify_credentials(conn)
|
||||
|
||||
@doc """
|
||||
Retrieve account
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - account identifier
|
||||
|
||||
"""
|
||||
@spec account(Hunter.Client.t, non_neg_integer) :: Hunter.Account.t
|
||||
def account(conn, id), do: Hunter.Account.account(conn, id)
|
||||
|
||||
@doc """
|
||||
Get a list of followers
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - account identifier
|
||||
|
||||
"""
|
||||
@spec followers(Hunter.Client.t, non_neg_integer) :: [Hunter.Account.t]
|
||||
def followers(conn, id), do: Hunter.Account.followers(conn, id)
|
||||
|
||||
@doc """
|
||||
Get a list of followed accounts
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - account identifier
|
||||
|
||||
"""
|
||||
@spec following(Hunter.Client.t, non_neg_integer) :: [Hunter.Account.t]
|
||||
def following(conn, id), do: Hunter.Account.following(conn, id)
|
||||
|
||||
@doc """
|
||||
Follow a remote user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `uri` - URI of the remote user, in the format of `username@domain`
|
||||
|
||||
"""
|
||||
@spec follow_by_uri(Hunter.Client.t, URI.t) :: Hunter.Account.t
|
||||
def follow_by_uri(conn, uri), do: Hunter.Account.follow_by_uri(conn, uri)
|
||||
|
||||
@doc """
|
||||
Register a new OAuth client app on the target instance
|
||||
|
||||
## Parameters
|
||||
|
||||
* `name`
|
||||
* `redirect_uri`
|
||||
* `scopes`
|
||||
* `website`
|
||||
|
||||
"""
|
||||
@spec create_app(String.t, URI.t, String.t, String.t) :: Hunter.Application.t
|
||||
def create_app(name, redirect_uri, scopes \\ "read", website \\ nil) do
|
||||
Hunter.Application.create_app(name, redirect_uri, scopes, website)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Initializes a client
|
||||
|
||||
## Options
|
||||
|
||||
* `base_url` - URL of the instance you want to connect to
|
||||
* `bearer_token` - [String] OAuth access token for your authenticated user
|
||||
|
||||
"""
|
||||
@spec new(Keyword.t) :: Hunter.Client.t
|
||||
def new(options \\ []), do: Hunter.Client.new(options)
|
||||
|
||||
@doc """
|
||||
User agent of the client
|
||||
"""
|
||||
@spec user_agent() :: String.t
|
||||
def user_agent, do: Hunter.Client.user_agent()
|
||||
|
||||
@doc """
|
||||
Upload a media file
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `file`
|
||||
|
||||
"""
|
||||
@spec upload_media(Hunter.Client.t, Path.t) :: Hunter.Media.t
|
||||
def upload_media(conn, file), do: Hunter.Media.upload_media(conn, file)
|
||||
|
||||
@doc """
|
||||
Get the relationships of authenticated user towards given other users
|
||||
|
||||
## Parameters
|
||||
|
||||
* `id` - list of relationship IDs
|
||||
|
||||
"""
|
||||
@spec relationships([non_neg_integer]) :: [Hunter.Relationship.t]
|
||||
def relationships(ids), do: Hunter.Relationship.relationships(ids)
|
||||
|
||||
@doc """
|
||||
Follow a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user identifier
|
||||
|
||||
"""
|
||||
@spec follow(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def follow(conn, id), do: Hunter.Relationship.follow(conn, id)
|
||||
|
||||
@doc """
|
||||
Unfollow a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user identifier
|
||||
|
||||
"""
|
||||
@spec unfollow(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def unfollow(conn, id), do: Hunter.Relationship.unfollow(conn, id)
|
||||
|
||||
@doc """
|
||||
Block a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user identifier
|
||||
|
||||
"""
|
||||
@spec block(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def block(conn, id), do: Hunter.Relationship.block(conn, id)
|
||||
|
||||
@doc """
|
||||
Unblock a user
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user identifier
|
||||
|
||||
"""
|
||||
@spec unblock(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def unblock(conn, id), do: Hunter.Relationship.unblock(conn, id)
|
||||
|
||||
@doc """
|
||||
Mute a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user identifier
|
||||
|
||||
"""
|
||||
@spec mute(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def mute(conn, id), do: Hunter.Relationship.mute(conn, id)
|
||||
|
||||
@doc """
|
||||
Unmute a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user identifier
|
||||
|
||||
"""
|
||||
@spec unmute(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def unmute(conn, id), do: Hunter.Relationship.unmute(conn, id)
|
||||
|
||||
@doc """
|
||||
Search for content
|
||||
|
||||
# Parameters
|
||||
|
||||
* `q` - search query
|
||||
|
||||
## Options
|
||||
|
||||
* `resolve` - whether to resolve non-local accounts
|
||||
|
||||
"""
|
||||
@spec search(String.t, Keyword.t) :: Hunter.Result.t
|
||||
def search(query, options \\ []), do: Hunter.Result.search(query, options)
|
||||
|
||||
@doc """
|
||||
Create new status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `text` - [String]
|
||||
* `in_reply_to_id` - [Integer]
|
||||
* `media_ids` - [Array<Integer>]
|
||||
|
||||
"""
|
||||
@spec create_status(Hunter.Client.t, String.t, non_neg_integer, [non_neg_integer]) :: Hunter.Status.t
|
||||
def create_status(conn, text, in_reply_to_id \\ nil, media_ids \\ []) do
|
||||
Hunter.Status.create_status(conn, text, in_reply_to_id, media_ids)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Retrieve status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@spec status(Hunter.Client.t, non_neg_integer) :: Hunter.Status.t
|
||||
def status(conn, id), do: Hunter.Status.status(conn, id)
|
||||
|
||||
@doc """
|
||||
Destroy status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@spec destroy_status(Hunter.Client.t, non_neg_integer) :: boolean
|
||||
def destroy_status(conn, id), do: Hunter.Status.destroy_status(conn, id)
|
||||
|
||||
@doc """
|
||||
Reblog a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@spec reblog(Hunter.Client.t, non_neg_integer) :: Hunter.Status.t
|
||||
def reblog(conn, id), do: Hunter.Status.reblog(conn, id)
|
||||
|
||||
@doc """
|
||||
Undo a reblog of a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@spec unreblog(Hunter.Client.t, non_neg_integer) :: Hunter.Status.t
|
||||
def unreblog(conn, id), do: Hunter.Status.unreblog(conn, id)
|
||||
|
||||
@doc """
|
||||
Favorite a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@spec favourite(Hunter.Client.t, non_neg_integer) :: Hunter.Status.t
|
||||
def favourite(conn, id), do: Hunter.Status.favourite(conn, id)
|
||||
|
||||
@doc """
|
||||
Undo a favorite of a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@spec unfavourite(Hunter.Client.t, non_neg_integer) :: Hunter.Status.t
|
||||
def unfavourite(conn, id), do: Hunter.Status.unfavourite(conn, id)
|
||||
|
||||
@doc """
|
||||
Get a list of statuses by a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials -
|
||||
* `account_id` - account identifier
|
||||
* `options` - option list
|
||||
|
||||
## Options
|
||||
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@spec statuses(Hunter.Client.t, non_neg_integer, Keyword.t) :: [Hunter.Status.t]
|
||||
def statuses(conn, account_id, options \\ []) do
|
||||
Hunter.Status.statuses(conn, account_id, options)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Retrieve statuses from the home timeline
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `options` - option list
|
||||
|
||||
## Options
|
||||
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@spec home_timeline(Hunter.Client.t, Keyword.t) :: [Hunter.Status.t]
|
||||
def home_timeline(conn, options \\ []) do
|
||||
Hunter.Status.home_timeline(conn, options)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Retrieve statuses from the public timeline
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `options` - option list
|
||||
|
||||
## Options
|
||||
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@spec public_timeline(Hunter.Client.t, Keyword.t) :: [Hunter.Status.t]
|
||||
def public_timeline(conn, options \\ []) do
|
||||
Hunter.Status.public_timeline(conn, options)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Retrieve statuses from a hashtag
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `hashtag` - string list
|
||||
|
||||
## Options
|
||||
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@spec hashtag_timeline(Hunter.Client.t, Keyword.t) :: [Hunter.Status.t]
|
||||
def hashtag_timeline(conn, hashtag, options \\ []) do
|
||||
Hunter.Status.hashtag_timeline(conn, hashtag, options)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns Hunter version
|
||||
"""
|
||||
@spec version() :: String.t
|
||||
def version, do: @hunter_version
|
||||
end
|
|
@ -0,0 +1,127 @@
|
|||
defmodule Hunter.Account do
|
||||
@moduledoc """
|
||||
Account entity
|
||||
|
||||
This module defines a `Hunter.Account` struct and the main functions
|
||||
for working with Accounts.
|
||||
|
||||
## Fields
|
||||
|
||||
* `id` - the ID of the account
|
||||
* `username` - the username of the account
|
||||
* `acct` - equals `username` for local users, includes `@domain` for remote ones
|
||||
* `display_name` - the account's display name
|
||||
* `note` - Biography of user
|
||||
* `url` - URL of the user's profile page (can be remote)
|
||||
* `avatar` - URL to the avatar image
|
||||
* `header` - URL to the header image
|
||||
* `locked` - boolean for when the account cannot be followed without waiting for approval first
|
||||
* `created_at` - the time the account was created
|
||||
* `followers_count` - the number of followers for the account
|
||||
* `following_count` - the number of accounts the given account is following
|
||||
* `statuses_count` - the number of statuses the account has made
|
||||
|
||||
"""
|
||||
@hunter_api Application.get_env(:hunter, :hunter_api)
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
id: non_neg_integer,
|
||||
username: String.t,
|
||||
acct: String.t,
|
||||
display_name: String.t,
|
||||
note: String.t,
|
||||
url: URI.t,
|
||||
avatar: URI.t,
|
||||
header: URI.t,
|
||||
locked: String.t,
|
||||
created_at: String.t,
|
||||
followers_count: non_neg_integer,
|
||||
following_count: non_neg_integer,
|
||||
statuses_count: non_neg_integer
|
||||
}
|
||||
|
||||
@derive [Poison.Encoder]
|
||||
defstruct [:id,
|
||||
:username,
|
||||
:acct,
|
||||
:display_name,
|
||||
:note,
|
||||
:url,
|
||||
:avatar,
|
||||
:header,
|
||||
:locked,
|
||||
:created_at,
|
||||
:followers_count,
|
||||
:following_count,
|
||||
:statuses_count]
|
||||
|
||||
|
||||
@doc """
|
||||
Retrieve account of authenticated user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
|
||||
"""
|
||||
@spec verify_credentials(Hunter.Client.t) :: Hunter.Account.t
|
||||
def verify_credentials(conn) do
|
||||
@hunter_api.verify_credentials(conn)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Retrieve account
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id`
|
||||
|
||||
"""
|
||||
@spec account(Hunter.Client.t, non_neg_integer) :: Hunter.Account.t
|
||||
def account(conn, id) do
|
||||
@hunter_api.account(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Get a list of followers
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id`
|
||||
|
||||
"""
|
||||
@spec followers(Hunter.Client.t, non_neg_integer) :: [Hunter.Account.t]
|
||||
def followers(conn, id) do
|
||||
@hunter_api.followers(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Get a list of followed accounts
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id`
|
||||
|
||||
"""
|
||||
@spec following(Hunter.Client.t, non_neg_integer) :: [Hunter.Account.t]
|
||||
def following(conn, id) do
|
||||
@hunter_api.following(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Follow a remote user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `uri` - URI of the remote user, in the format of username@domain
|
||||
|
||||
"""
|
||||
@spec follow_by_uri(Hunter.Client.t, URI.t) :: Hunter.Account.t
|
||||
def follow_by_uri(conn, uri) do
|
||||
@hunter_api.follow_by_uri(conn, uri)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,329 @@
|
|||
defmodule Hunter.Api do
|
||||
## Account
|
||||
|
||||
@doc """
|
||||
Retrieve account of authenticated user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
|
||||
"""
|
||||
@callback verify_credentials(conn :: Hunter.Client.t) :: Hunter.Account.t
|
||||
|
||||
@doc """
|
||||
Retrieve account
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - account identifier
|
||||
|
||||
"""
|
||||
@callback account(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Account.t
|
||||
|
||||
@doc """
|
||||
Get a list of followers
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - account identifier
|
||||
|
||||
"""
|
||||
@callback followers(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Account.t
|
||||
|
||||
@doc """
|
||||
Get a list of followed accounts
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - account identifier
|
||||
|
||||
"""
|
||||
@callback following(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Account.t
|
||||
|
||||
@doc """
|
||||
Follow a remote user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `uri` - URI of the remote user, in the format of `username@domain`
|
||||
|
||||
"""
|
||||
@callback follow_by_uri(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Account.t
|
||||
|
||||
## Application
|
||||
|
||||
@doc """
|
||||
Register a new OAuth client app on the target instance
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `name`
|
||||
* `redirect_uri`
|
||||
* `scopes`
|
||||
* `website`
|
||||
|
||||
"""
|
||||
@callback create_app(conn :: Hunter.Client.t, name :: String.t, redirect_uri :: URI.t, scopes :: String.t, website :: String.t) :: Hunter.Application.t
|
||||
|
||||
@doc """
|
||||
Upload a media file
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `file` -
|
||||
|
||||
"""
|
||||
@callback upload_media(conn :: Hunter.Client.t, file :: Path.t) :: Hunter.Media.t
|
||||
|
||||
|
||||
## Relationship
|
||||
|
||||
@doc """
|
||||
Get the relationships of authenticated user towards given other users
|
||||
|
||||
## Parameters
|
||||
|
||||
* `id` - list of relationship IDs
|
||||
|
||||
"""
|
||||
@callback relationships(ids :: [non_neg_integer]) :: [Hunter.Relationship.t]
|
||||
|
||||
@doc """
|
||||
Follow a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user id
|
||||
|
||||
"""
|
||||
@callback follow(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Relationship.t
|
||||
|
||||
@doc """
|
||||
Unfollow a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user identifier
|
||||
|
||||
"""
|
||||
@callback unfollow(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Relationship.t
|
||||
|
||||
@doc """
|
||||
Block a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user identifier
|
||||
|
||||
"""
|
||||
@callback block(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Relationship.t
|
||||
|
||||
@doc """
|
||||
Unblock a user
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user identifier
|
||||
|
||||
"""
|
||||
@callback unblock(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Relationship.t
|
||||
|
||||
@doc """
|
||||
Mute a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user identifier
|
||||
|
||||
"""
|
||||
@callback mute(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Relationship.t
|
||||
|
||||
@doc """
|
||||
Unmute a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - user identifier
|
||||
|
||||
"""
|
||||
@callback unmute(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Relationship.t
|
||||
|
||||
## Result
|
||||
|
||||
@doc """
|
||||
Search for content
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `q` - the search query
|
||||
* `options` - option list
|
||||
|
||||
## Options
|
||||
|
||||
* `resolve` - whether to resolve non-local accounts
|
||||
|
||||
"""
|
||||
@callback search(Hunter.Client.t, query :: String.t, options :: Keyword.t) :: Hunter.Result.t
|
||||
|
||||
## Status
|
||||
|
||||
@doc """
|
||||
Create new status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `text` - [String]
|
||||
* `in_reply_to_id` - [Integer]
|
||||
* `media_ids` - [Array<Integer>]
|
||||
|
||||
"""
|
||||
@callback create_status(conn :: Hunter.Client.t, text :: String.t, in_reply_to_id :: non_neg_integer, media_ids :: [non_neg_integer]) :: Hunter.Status.t
|
||||
|
||||
@doc """
|
||||
Retrieve status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@callback status(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Status
|
||||
|
||||
@doc """
|
||||
Destroy status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@callback destroy_status(conn :: Hunter.Client.t, id :: non_neg_integer) :: boolean
|
||||
|
||||
@doc """
|
||||
Reblog a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@callback reblog(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Status.t
|
||||
|
||||
@doc """
|
||||
Undo a reblog of a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@callback unreblog(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Status.t
|
||||
|
||||
@doc """
|
||||
Favorite a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@callback favourite(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Status.t
|
||||
|
||||
@doc """
|
||||
Undo a favorite of a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `id` - status identifier
|
||||
|
||||
"""
|
||||
@callback unfavourite(conn :: Hunter.Client.t, id :: non_neg_integer) :: Hunter.Status.t
|
||||
|
||||
@doc """
|
||||
Get a list of statuses by a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `account_id` - account identifier
|
||||
* `options` - option list
|
||||
|
||||
## Options
|
||||
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@callback statuses(conn :: Hunter.Client.t, account_id :: non_neg_integer, options :: Keyword.t) :: [Hunter.Status.t]
|
||||
|
||||
@doc """
|
||||
Retrieve statuses from the home timeline
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `options` - option list
|
||||
|
||||
## Options
|
||||
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@callback home_timeline(conn :: Hunter.Client.t, options :: Keyword.t) :: [Hunter.Status.t]
|
||||
|
||||
@doc """
|
||||
Retrieve statuses from the public timeline
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `options` - option list
|
||||
|
||||
## Options
|
||||
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@callback public_timeline(conn :: Hunter.Client.t, options :: Keyword.t) :: [Hunter.Status.t]
|
||||
|
||||
@doc """
|
||||
Retrieve statuses from a hashtag
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `hashtag` - list of strings
|
||||
|
||||
## Options
|
||||
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@callback hashtag_timeline(conn :: Hunter.Client.t, hashtag :: [String.t], options :: Keyword.t) :: [Hunter.Status]
|
||||
end
|
|
@ -0,0 +1,183 @@
|
|||
defmodule Hunter.Api.HTTPClient do
|
||||
@behaviour Hunter.Api
|
||||
|
||||
def verify_credentials(%Hunter.Client{base_url: base_url} = conn) do
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.get(base_url <> "/api/v1/accounts/verify_credentials", get_headers(conn))
|
||||
Poison.decode!(body, as: %Hunter.Account{})
|
||||
end
|
||||
|
||||
def account(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.get(base_url <> "/api/v1/accounts/#{id}", get_headers(conn))
|
||||
Poison.decode!(body, as: %Hunter.Account{})
|
||||
end
|
||||
|
||||
def followers(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.get(base_url <> "/api/v1/accounts/#{id}/followers", get_headers(conn))
|
||||
Poison.decode!(body, as: [%Hunter.Account{}])
|
||||
end
|
||||
|
||||
def following(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.get(base_url <> "/api/v1/accounts/#{id}/following", get_headers(conn))
|
||||
Poison.decode!(body, as: [%Hunter.Account{}])
|
||||
end
|
||||
|
||||
def follow_by_uri(%Hunter.Client{base_url: base_url} = conn, uri) do
|
||||
payload = Poison.encode!(%{uri: uri})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/follows", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Account{})
|
||||
end
|
||||
|
||||
def create_app(%Hunter.Client{base_url: base_url} = conn, name, redirect_uri, scopes, website) do
|
||||
payload = Poison.encode!(%{client_name: name, redirect_uris: redirect_uri, scopes: scopes, website: website})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/apps", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Application{})
|
||||
end
|
||||
|
||||
def upload_media(%Hunter.Client{base_url: base_url} = conn, file) do
|
||||
payload = Poison.encode!(%{file: file})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/media", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Media{})
|
||||
end
|
||||
|
||||
def relationships(_ids) do
|
||||
# :: [Hunter.Relationship.t]
|
||||
# @return [Hunter::Collection<Hunter::Relationship>]
|
||||
# perform_request_with_collection(:get, '', array_param(:id, ids), Hunter::Relationship)
|
||||
HTTPoison.get("/api/v1/accounts/relationships")
|
||||
|
||||
# Poison.decode!(body, as: [%Hunter.Relationship{}])
|
||||
end
|
||||
|
||||
def follow(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
payload = Poison.encode!(%{})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/accounts/#{id}/follow", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Relationship{})
|
||||
end
|
||||
|
||||
def unfollow(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
payload = Poison.encode!(%{})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/accounts/#{id}/unfollow", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Relationship{})
|
||||
end
|
||||
|
||||
def block(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
payload = Poison.encode!(%{})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/accounts/#{id}/block", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Relationship{})
|
||||
end
|
||||
|
||||
def unblock(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
payload = Poison.encode!(%{})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/accounts/#{id}/unblock", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Relationship{})
|
||||
end
|
||||
|
||||
def mute(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
payload = Poison.encode!(%{})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/accounts/#{id}/mute", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Relationship{})
|
||||
end
|
||||
|
||||
def unmute(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
payload = Poison.encode!(%{})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/accounts/#{id}/unmute", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Relationship{})
|
||||
end
|
||||
|
||||
def search(_conn, _query, _options) do
|
||||
# :: Hunter.Result.t
|
||||
|
||||
# @return [Hunter::Results] If q is a URL, Hunter will
|
||||
# attempt to fetch the provided account or status. Otherwise, it
|
||||
# will do a local account and hashtag search.
|
||||
|
||||
# opts = {
|
||||
# q: query,
|
||||
# }.merge(options)
|
||||
|
||||
# perform_request_with_object(:get, '/api/v1/search', opts, Hunter::Results)
|
||||
end
|
||||
|
||||
def create_status(%Hunter.Client{base_url: base_url} = conn, text, in_reply_to_id, _media_ids) do
|
||||
payload = Poison.encode!(%{status: text, in_reply_to_id: in_reply_to_id})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/statuses", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Status{})
|
||||
end
|
||||
|
||||
def status(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.get(base_url <> "/api/v1/statuses/#{id}", get_headers(conn))
|
||||
Poison.decode(body, as: %Hunter.Status{})
|
||||
end
|
||||
|
||||
def destroy_status(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
case HTTPoison.delete(base_url <> "/api/v1/statuses/#{id}", get_headers(conn)) do
|
||||
{:ok, %HTTPoison.Response{status_code: 200}} ->
|
||||
true
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def reblog(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
payload = Poison.encode!(%{})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/statuses/#{id}/reblog", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Status{})
|
||||
end
|
||||
|
||||
def unreblog(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
payload = Poison.encode!(%{})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/statuses/#{id}/unreblog", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Status{})
|
||||
end
|
||||
|
||||
def favourite(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
payload = Poison.encode!(%{})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/statuses/#{id}/favourite", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Status{})
|
||||
end
|
||||
|
||||
def unfavourite(%Hunter.Client{base_url: base_url} = conn, id) do
|
||||
payload = Poison.encode!(%{})
|
||||
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.post(base_url <> "/api/v1/statuses/#{id}/unfavourite", payload, [{"Content-Type", "application/json"} | get_headers(conn)])
|
||||
Poison.decode!(body, as: %Hunter.Status{})
|
||||
end
|
||||
|
||||
def statuses(%Hunter.Client{base_url: base_url} = conn, account_id, options) do
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.get(base_url <> "/api/v1/accounts/#{account_id}/statuses", get_headers(conn), options)
|
||||
Poison.decode!(body, as: [%Hunter.Status{}])
|
||||
end
|
||||
|
||||
def home_timeline(%Hunter.Client{base_url: base_url} = conn, options) do
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.get(base_url <> "/api/v1/timelines/home", get_headers(conn), options)
|
||||
Poison.decode!(body, as: [%Hunter.Status{}])
|
||||
end
|
||||
|
||||
def public_timeline(%Hunter.Client{base_url: base_url} = conn, options) do
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.get(base_url <> "/api/v1/timelines/public", get_headers(conn), options)
|
||||
Poison.decode!(body, as: [%Hunter.Status{}])
|
||||
end
|
||||
|
||||
def hashtag_timeline(%Hunter.Client{base_url: base_url} = conn, hashtag, options) do
|
||||
{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.get(base_url <> "/api/v1/timelines/tag/#{hashtag}", get_headers(conn), options)
|
||||
Poison.decode!(body, as: [%Hunter.Status{}])
|
||||
end
|
||||
|
||||
## Helpers
|
||||
defp get_headers(%Hunter.Client{bearer_token: token}) do
|
||||
[{"Authorization", "Bearer #{token}"}]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,52 @@
|
|||
defmodule Hunter.Application do
|
||||
@moduledoc """
|
||||
Application entity
|
||||
|
||||
This module defines a `Hunter.Application` struct and the main functions
|
||||
for working with Applications.
|
||||
|
||||
## Fields
|
||||
|
||||
* `name` - name of the application
|
||||
* `website` - homepage URL of the application
|
||||
* `scope` - access scopes
|
||||
* `redirect_uri` -
|
||||
|
||||
## Scopes
|
||||
|
||||
* `read` - read data
|
||||
* `write` - post statuses and upload media for statuses
|
||||
* `follow` - follow, unfollow, block, unblock
|
||||
|
||||
Multiple scopes can be requested during the authorization phase with the `scope` query param
|
||||
|
||||
"""
|
||||
@hunter_api Application.get_env(:hunter, :hunter_api)
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
name: String.t,
|
||||
redirect_uri: URI.t,
|
||||
scopes: String.t,
|
||||
website: URI.t
|
||||
}
|
||||
|
||||
@derive [Poison.Encoder]
|
||||
defstruct [:name, :redirect_uri, :scopes, :website]
|
||||
|
||||
@doc """
|
||||
Register a new OAuth client app on the target instance
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `name` -
|
||||
* `redirect_uri` -
|
||||
* `scopes` -
|
||||
* `website` -
|
||||
|
||||
"""
|
||||
@spec create_app(Hunter.Client.t, String.t, URI.t, String.t, String.t) :: Hunter.Application.t
|
||||
def create_app(conn, name, redirect_uri, scopes \\ "read", website \\ nil) do
|
||||
@hunter_api.create_app(conn, name, redirect_uri, scopes, website)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
defmodule Hunter.Attribute do
|
||||
@moduledoc """
|
||||
Attribute entity
|
||||
|
||||
This module defines a `Hunter.Attribute` struct and the main functions
|
||||
for working with Attributes.
|
||||
|
||||
## Fields
|
||||
|
||||
* `id` - ID of the attachment
|
||||
* `type` - One of: "image", "video", "gifv"
|
||||
* `url` - URL of the locally hosted version of the image
|
||||
* `remote_url` - For remote images, the remote URL of the original image
|
||||
* `preview_url` - URL of the preview image
|
||||
* `text_url` - Shorter URL for the image, for insertion into text (only present on local images)
|
||||
|
||||
"""
|
||||
@type t :: %__MODULE__{
|
||||
id: non_neg_integer,
|
||||
type: String.t,
|
||||
url: URI.t,
|
||||
remote_url: URI.t,
|
||||
preview_url: URI.t,
|
||||
text_url: URI.t
|
||||
}
|
||||
|
||||
@derive [Poison.Encoder]
|
||||
defstruct [:id, :type, :url, :remote_url, :preview_url, :text_url]
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
defmodule Hunter.Card do
|
||||
@moduledoc """
|
||||
Card entity
|
||||
|
||||
This module defines a `Hunter.Card` struct and the main functions
|
||||
for working with Cards
|
||||
|
||||
## Fields
|
||||
|
||||
* `url`- The url associated with the card
|
||||
* `title` - The title of the card
|
||||
* `description` - The card description
|
||||
* `image` - The image associated with the card, if any
|
||||
|
||||
"""
|
||||
@type t :: %__MODULE__{
|
||||
url: URI.t,
|
||||
title: String.t,
|
||||
description: String.t,
|
||||
image: String.t
|
||||
}
|
||||
|
||||
@derive [Poison.Encoder]
|
||||
defstruct [:url, :title, :description, :image]
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
defmodule Hunter.Client do
|
||||
@moduledoc """
|
||||
Defines a `Hunter` client
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
base_url: URI.t,
|
||||
bearer_token: String.t
|
||||
|
||||
}
|
||||
|
||||
@derive [Poison.Encoder]
|
||||
defstruct [:base_url, :bearer_token]
|
||||
|
||||
@doc """
|
||||
Initializes a client
|
||||
|
||||
## Options
|
||||
|
||||
* `base_url` - URL of the instance you want to connect to
|
||||
* `bearer_token` - [String] OAuth access token for your authenticated user
|
||||
|
||||
"""
|
||||
@spec new(Keyword.t) :: Hunter.Client.t
|
||||
def new(options \\ []) do
|
||||
struct(Hunter.Client, options)
|
||||
end
|
||||
|
||||
@doc """
|
||||
User agent of the client
|
||||
"""
|
||||
@spec user_agent() :: String.t
|
||||
def user_agent do
|
||||
"Hunter.Elixir/#{Hunter.version}"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
defmodule Hunter.Context do
|
||||
@moduledoc """
|
||||
Context entity
|
||||
|
||||
## Fields
|
||||
|
||||
* `ancestors` - The ancestors of the status in the conversation, as a list of Statuses
|
||||
* `descendants` - The descendants of the status in the conversation, as a list of Statuses
|
||||
|
||||
"""
|
||||
defstruct [:ancestors, :descendants]
|
||||
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
defmodule Hunter.Instance do
|
||||
@moduledoc """
|
||||
Instance entity
|
||||
|
||||
This module defines a `Hunter.Instance` struct and the main functions
|
||||
for working with Instances.
|
||||
|
||||
## Fields
|
||||
|
||||
* `uri` - URI of the current instance
|
||||
* `title` - The instance's title
|
||||
* `description` - A description for the instance
|
||||
* `email` - An email address which can be used to contact the instance administrator
|
||||
|
||||
"""
|
||||
@type t :: %__MODULE__{
|
||||
uri: URI.t,
|
||||
title: String.t,
|
||||
description: String.t,
|
||||
email: String.t
|
||||
}
|
||||
|
||||
defstruct [:uri, :title, :description, :email]
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
defmodule Hunter.Media do
|
||||
|
||||
@hunter_api Application.get_env(:hunter, :hunter_api)
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
id: non_neg_integer,
|
||||
url: URI.t,
|
||||
preview_url: URI.t,
|
||||
type: String.t
|
||||
}
|
||||
|
||||
@derive [Poison.Encoder]
|
||||
defstruct [:id, :url, :preview_url, :type]
|
||||
|
||||
@doc """
|
||||
Upload a media file
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `file` - [HTTP::FormData::File]
|
||||
|
||||
"""
|
||||
@spec upload_media(Hunter.Client.t, Path.t) :: Hunter.Media.t
|
||||
def upload_media(conn, file) do
|
||||
@hunter_api.upload_media(conn, file)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
defmodule Hunter.Mention do
|
||||
@moduledoc """
|
||||
Mention entity
|
||||
|
||||
## Fields
|
||||
|
||||
* `url` - URL of user's profile (can be remote)
|
||||
* `username` - The username of the account
|
||||
* `acct` - Equals `username` for local users, includes `@domain` for remote ones
|
||||
* `id` - Account ID
|
||||
|
||||
"""
|
||||
@type t :: %__MODULE__{
|
||||
url: URI.t,
|
||||
username: String.t,
|
||||
acct: String.t,
|
||||
id: non_neg_integer
|
||||
}
|
||||
|
||||
@derive [Poison.Encoder]
|
||||
defstruct [:url, :username, :acct, :id]
|
||||
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
defmodule Hunter.Notification do
|
||||
@moduledoc """
|
||||
Notification entity
|
||||
|
||||
This module defines a `Hunter.Notification` struct and the main functions
|
||||
for working with Notifications.
|
||||
|
||||
## Fields
|
||||
|
||||
* `id` - The notification ID
|
||||
* `type` - One of: "mention", "reblog", "favourite", "follow"
|
||||
* `created_at` - The time the notification was created
|
||||
* `account` - The `Hunter.Account` sending the notification to the user
|
||||
* `status` - The `Hunter.Status` associated with the notification, if applicable
|
||||
|
||||
"""
|
||||
@type t :: %__MODULE__{
|
||||
id: String.t,
|
||||
type: String.t,
|
||||
created_at: String.t,
|
||||
account: Hunter.Account.t,
|
||||
status: Hunter.Status.t
|
||||
}
|
||||
|
||||
@derive [Poison.Encoder]
|
||||
defstruct [:id, :type, :created_at, :account, :status]
|
||||
end
|
|
@ -0,0 +1,124 @@
|
|||
defmodule Hunter.Relationship do
|
||||
@moduledoc """
|
||||
Relationship entity
|
||||
|
||||
This module defines a `Hunter.Relationship` struct and the main functions
|
||||
for working with Relationship.
|
||||
|
||||
## Fields
|
||||
|
||||
* `following` - Whether the user is currently following the account
|
||||
* `followed_by` - Whether the user is currently being followed by the account
|
||||
* `blocking` - Whether the user is currently blocking the account
|
||||
* `muting` - Whether the user is currently muting the account
|
||||
* `requested` - Whether the user has requested to follow the account
|
||||
|
||||
"""
|
||||
@hunter_api Application.get_env(:hunter, :hunter_api)
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
following: boolean,
|
||||
followed_by: boolean,
|
||||
blocking: boolean,
|
||||
muting: boolean,
|
||||
requested: boolean
|
||||
}
|
||||
|
||||
@derive [Poison.Encoder]
|
||||
defstruct [:following, :followed_by, :blocking, :muting, :requested]
|
||||
|
||||
@doc """
|
||||
Get the relationships of authenticated user towards given other users
|
||||
|
||||
## Parameters
|
||||
|
||||
* `id` - list of relationship IDs
|
||||
|
||||
"""
|
||||
@spec relationships([non_neg_integer]) :: [Hunter.Relationship.t]
|
||||
def relationships(ids) do
|
||||
@hunter_api.relationships(ids)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Follow a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id` - user id
|
||||
|
||||
"""
|
||||
@spec follow(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def follow(conn, id) do
|
||||
@hunter_api.follow(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Unfollow a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id`
|
||||
|
||||
"""
|
||||
@spec unfollow(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def unfollow(conn, id) do
|
||||
@hunter_api.unfollow(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Block a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id`
|
||||
|
||||
"""
|
||||
@spec block(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def block(conn, id) do
|
||||
@hunter_api.block(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Unblock a user
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id`
|
||||
|
||||
"""
|
||||
@spec unblock(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def unblock(conn, id) do
|
||||
@hunter_api.unblock(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Mute a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id`
|
||||
|
||||
"""
|
||||
@spec mute(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def mute(conn, id) do
|
||||
@hunter_api.mute(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Unmute a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id`
|
||||
|
||||
"""
|
||||
@spec unmute(Hunter.Client.t, non_neg_integer) :: Hunter.Relationship.t
|
||||
def unmute(conn, id) do
|
||||
@hunter_api.unmute(conn, id)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
defmodule Hunter.Report do
|
||||
@moduledoc """
|
||||
Report entity
|
||||
|
||||
This module defines a `Hunter.Report` struct and the main functions
|
||||
for working with Reports.
|
||||
|
||||
## Fields
|
||||
|
||||
* `id` - The ID of the report
|
||||
* `action_taken` - The action taken in response to the report
|
||||
|
||||
"""
|
||||
defstruct [:id, :action_taken]
|
||||
end
|
|
@ -0,0 +1,42 @@
|
|||
defmodule Hunter.Result do
|
||||
@moduledoc """
|
||||
Result entity
|
||||
|
||||
## Fields
|
||||
|
||||
* `accounts` - list of matched `Hunter.Account`
|
||||
* `statuses` - list of matched `Hunter.Status`
|
||||
* `hashtags` - list of matched hashtags, as strings
|
||||
|
||||
"""
|
||||
@hunter_api Application.get_env(:hunter, :hunter_api)
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
accounts: [Hunter.Account.t],
|
||||
statuses: [Hunter.Status.t],
|
||||
hashtags: [String.t]
|
||||
}
|
||||
|
||||
@derive [Poison.Encoder]
|
||||
defstruct accounts: [],
|
||||
statuses: [],
|
||||
hashtags: []
|
||||
|
||||
@doc """
|
||||
Search for content
|
||||
|
||||
# Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `q` - [String] The search query
|
||||
|
||||
## Options
|
||||
|
||||
* `resolve` - [Boolean] Whether to resolve non-local accounts
|
||||
|
||||
"""
|
||||
@spec search(Hunter.Client.t, String.t, Keyword.t) :: Hunter.Result.t
|
||||
def search(conn, query, options \\ []) do
|
||||
@hunter_api.search(conn, query, options)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,255 @@
|
|||
defmodule Hunter.Status do
|
||||
@moduledoc """
|
||||
Status entity
|
||||
|
||||
## Fields
|
||||
|
||||
* `id` - The ID of the status
|
||||
* `uri` - A Fediverse-unique resource ID
|
||||
* `url` - URL to the status page (can be remote)
|
||||
* `account` - The `Hunter.Account` which posted the status
|
||||
* `in_reply_to_id` - `nil` or the ID of the status it replies to
|
||||
* `in_reply_to_account_id` - `nil` or the ID of the account it replies to
|
||||
* `reblog` - `nil` or the reblogged `Hunter.Status`
|
||||
* `content` - Body of the status; this will contain HTML (remote HTML already sanitized)
|
||||
* `created_at` - The time the status was created
|
||||
* `reblogs_count` - The number of reblogs for the status
|
||||
* `favourites_count` - The number of favourites for the status
|
||||
* `reblogged` - Whether the authenticated user has reblogged the status
|
||||
* `favourited` - Whether the authenticated user has favourited the status
|
||||
* `sensitive` - Whether media attachments should be hidden by default
|
||||
* `spoiler_text` - If not empty, warning text that should be displayed before the actual content
|
||||
* `visibility` - One of: `public`, `unlisted`, `private`, `direct`
|
||||
* `media_attachments` - A list of `Hunter.Attachment`
|
||||
* `mentions` - A list of `Hunter.Mention`
|
||||
* `tags` - A list of `Hunter.Tag`
|
||||
* `application` - `Hunter.Application` from which the status was posted
|
||||
|
||||
"""
|
||||
@hunter_api Application.get_env(:hunter, :hunter_api)
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
id: non_neg_integer,
|
||||
uri: URI.t,
|
||||
url: URI.t,
|
||||
account: Hunter.Account.t,
|
||||
in_reply_to_id: non_neg_integer,
|
||||
reblog: Hunter.Status.t | nil,
|
||||
content: String.t,
|
||||
created_at: String.t,
|
||||
reblogs_count: non_neg_integer,
|
||||
favourites_count: non_neg_integer,
|
||||
reblogged: boolean,
|
||||
favourited: boolean,
|
||||
sensitive: boolean,
|
||||
spoiler_text: String.t,
|
||||
media_attachments: [Hunter.Attachment.t],
|
||||
mentions: [Hunter.Mention.t],
|
||||
tags: [Hunter.Tag.t],
|
||||
application: Hunter.Application.t
|
||||
}
|
||||
|
||||
@derive [Poison.Encoder]
|
||||
defstruct [:id,
|
||||
:uri,
|
||||
:url,
|
||||
:account,
|
||||
:in_reply_to_id,
|
||||
:in_reply_to_account_id,
|
||||
:reblog,
|
||||
:content,
|
||||
:created_at,
|
||||
:reblogs_count,
|
||||
:favourites_count,
|
||||
:reblogged,
|
||||
:favourited,
|
||||
:sensitive,
|
||||
:spoiler_text,
|
||||
:visibility,
|
||||
:media_attachments,
|
||||
:mentions,
|
||||
:tags,
|
||||
:application]
|
||||
|
||||
@doc """
|
||||
Create new status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `text` - [String]
|
||||
* `in_reply_to_id` - [Integer]
|
||||
* `media_ids` - [Array<Integer>]
|
||||
|
||||
"""
|
||||
@spec create_status(Hunter.Client.t, String.t, non_neg_integer, [non_neg_integer]) :: Hunter.Status.t
|
||||
def create_status(conn, text, in_reply_to_id \\ nil, media_ids \\ []) do
|
||||
@hunter_api.create_status(conn, text, in_reply_to_id, media_ids)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Retrieve status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id` [Integer]
|
||||
|
||||
"""
|
||||
@spec status(Hunter.Client.t, non_neg_integer) :: Hunter.Status.t
|
||||
def status(conn, id) do
|
||||
@hunter_api.status(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Destroy status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id` [Integer]
|
||||
|
||||
"""
|
||||
@spec destroy_status(Hunter.Client.t, non_neg_integer) :: boolean
|
||||
def destroy_status(conn, id) do
|
||||
@hunter_api.destroy_status(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Reblog a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id` - [Integer]
|
||||
|
||||
"""
|
||||
@spec reblog(Hunter.Client.t, non_neg_integer) :: Hunter.Status.t
|
||||
def reblog(conn, id) do
|
||||
@hunter_api.reblog(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Undo a reblog of a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id` - [Integer]
|
||||
|
||||
"""
|
||||
@spec unreblog(Hunter.Client.t, non_neg_integer) :: Hunter.Status.t
|
||||
def unreblog(conn, id) do
|
||||
@hunter_api.unreblog(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Favorite a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id` - [Integer]
|
||||
|
||||
"""
|
||||
@spec favourite(Hunter.Client.t, non_neg_integer) :: Hunter.Status.t
|
||||
def favourite(conn, id) do
|
||||
@hunter_api.favourite(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Undo a favorite of a status
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `id` - [Integer]
|
||||
|
||||
"""
|
||||
@spec unfavourite(Hunter.Client.t, non_neg_integer) :: Hunter.Status.t
|
||||
def unfavourite(conn, id) do
|
||||
@hunter_api.unfavourite(conn, id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Get a list of statuses by a user
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `account_id` [Integer]
|
||||
* `options` - options
|
||||
|
||||
## Options
|
||||
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@spec statuses(Hunter.Client.t, non_neg_integer, Keyword.t) :: [Hunter.Status.t]
|
||||
def statuses(conn, account_id, options \\ []) do
|
||||
@hunter_api.statuses(conn, account_id, options)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Retrieve statuses from the home timeline
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `options` - option list
|
||||
|
||||
## Options
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@spec home_timeline(Hunter.Client.t, Keyword.t) :: [Hunter.Status.t]
|
||||
def home_timeline(conn, options \\ []) do
|
||||
@hunter_api.home_timeline(conn, options)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Retrieve statuses from the public timeline
|
||||
|
||||
## Parametes
|
||||
|
||||
* `conn` - Connection credentials
|
||||
* `options` - option list
|
||||
|
||||
## Options
|
||||
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@spec public_timeline(Hunter.Client.t, Keyword.t) :: [Hunter.Status.t]
|
||||
def public_timeline(conn, options \\ []) do
|
||||
@hunter_api.public_timeline(conn, options)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Retrieve statuses from a hashtag
|
||||
|
||||
## Parameters
|
||||
|
||||
* `conn` - connection credentials
|
||||
* `hashtag` - string list
|
||||
|
||||
## Options
|
||||
|
||||
* `max_id` - [Integer]
|
||||
* `since_id` - [Integer]
|
||||
* `limit` - [Integer]
|
||||
|
||||
"""
|
||||
@spec hashtag_timeline(Hunter.Client.t, Keyword.t) :: [Hunter.Status.t]
|
||||
def hashtag_timeline(conn, hashtag, options \\ []) do
|
||||
@hunter_api.hashtag_timeline(conn, hashtag, options)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
defmodule Hunter.Tag do
|
||||
@moduledoc """
|
||||
Tag entity
|
||||
|
||||
## Fields
|
||||
|
||||
* `name` - The hashtag, not including the preceding `#`
|
||||
* `url` - The URL of the hashtag
|
||||
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
name: String.t,
|
||||
url: URI.t
|
||||
}
|
||||
|
||||
defstruct [:name, :url]
|
||||
end
|
|
@ -0,0 +1,45 @@
|
|||
defmodule Hunter.Mixfile do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[app: :hunter,
|
||||
version: "0.1.0",
|
||||
elixir: "~> 1.3",
|
||||
docs: docs(),
|
||||
package: package(),
|
||||
source_url: "https://github.com/milmazz/hunter",
|
||||
description: "Elixir wrapper for Mastodon API",
|
||||
build_embedded: Mix.env == :prod,
|
||||
start_permanent: Mix.env == :prod,
|
||||
elixirc_paths: elixirc_paths(Mix.env),
|
||||
deps: deps()]
|
||||
end
|
||||
|
||||
# Configuration for the OTP application
|
||||
#
|
||||
# Type "mix help compile.app" for more information
|
||||
def application do
|
||||
# Specify extra applications you'll use from Erlang/Elixir
|
||||
[extra_applications: [:logger, :httpoison]]
|
||||
end
|
||||
|
||||
defp deps do
|
||||
[{:httpoison, "~> 0.10.0"},
|
||||
{:poison, "~> 3.0"},
|
||||
{:ex_doc, "~> 0.14", only: :dev, runtime: false}]
|
||||
end
|
||||
|
||||
defp package do
|
||||
[licenses: ["Apache 2.0"],
|
||||
maintainers: ["Milton Mazzarri"],
|
||||
links: %{"GitHub" => "https://github.com/milmazz/hunter"}]
|
||||
end
|
||||
|
||||
defp docs do
|
||||
[extras: ["README.md"], main: "readme"]
|
||||
end
|
||||
|
||||
# Specifies which paths to compile per environment
|
||||
defp elixirc_paths(:test), do: ["lib", "test/support"]
|
||||
defp elixirc_paths(_), do: ["lib"]
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
%{"certifi": {:hex, :certifi, "1.0.0", "1c787a85b1855ba354f0b8920392c19aa1d06b0ee1362f9141279620a5be2039", [:rebar3], []},
|
||||
"earmark": {:hex, :earmark, "1.2.0", "bf1ce17aea43ab62f6943b97bd6e3dc032ce45d4f787504e3adf738e54b42f3a", [:mix], []},
|
||||
"ex_doc": {:hex, :ex_doc, "0.15.0", "e73333785eef3488cf9144a6e847d3d647e67d02bd6fdac500687854dd5c599f", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]},
|
||||
"hackney": {:hex, :hackney, "1.6.6", "5564b4695d48fd87859e9df77a7fa4b4d284d24519f0cd7cc898f09e8fbdc8a3", [:rebar3], [{:certifi, "1.0.0", [hex: :certifi, optional: false]}, {:idna, "4.0.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]},
|
||||
"httpoison": {:hex, :httpoison, "0.10.0", "4727b3a5e57e9a4ff168a3c2883e20f1208103a41bccc4754f15a9366f49b676", [:mix], [{:hackney, "~> 1.6.3", [hex: :hackney, optional: false]}]},
|
||||
"idna": {:hex, :idna, "4.0.0", "10aaa9f79d0b12cf0def53038547855b91144f1bfcc0ec73494f38bb7b9c4961", [:rebar3], []},
|
||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []},
|
||||
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []},
|
||||
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []},
|
||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []}}
|
|
@ -0,0 +1,104 @@
|
|||
defmodule Hunter.Api.InMemory do
|
||||
@behaviour Hunter.Api
|
||||
|
||||
def verify_credentials(_) do
|
||||
%Hunter.Account{}
|
||||
end
|
||||
|
||||
def account(_, _) do
|
||||
%Hunter.Account{}
|
||||
end
|
||||
|
||||
def followers(_, _) do
|
||||
[%Hunter.Account{}]
|
||||
end
|
||||
|
||||
def following(_, _) do
|
||||
[%Hunter.Account{}]
|
||||
end
|
||||
|
||||
def follow_by_uri(_, _) do
|
||||
%Hunter.Account{}
|
||||
end
|
||||
|
||||
def create_app(_, _, _, _, _) do
|
||||
%Hunter.Application{}
|
||||
end
|
||||
|
||||
def upload_media(_, _) do
|
||||
%Hunter.Media{}
|
||||
end
|
||||
|
||||
def relationships(_) do
|
||||
end
|
||||
|
||||
def follow(_, _) do
|
||||
%Hunter.Relationship{}
|
||||
end
|
||||
|
||||
def unfollow(_, _) do
|
||||
%Hunter.Relationship{}
|
||||
end
|
||||
|
||||
def block(_, _) do
|
||||
%Hunter.Relationship{}
|
||||
end
|
||||
|
||||
def unblock(_, _) do
|
||||
%Hunter.Relationship{}
|
||||
end
|
||||
|
||||
def mute(_, _) do
|
||||
%Hunter.Relationship{}
|
||||
end
|
||||
|
||||
def unmute(_, _) do
|
||||
%Hunter.Relationship{}
|
||||
end
|
||||
|
||||
def search(_, _, _) do
|
||||
end
|
||||
|
||||
def create_status(_, _, _, _) do
|
||||
end
|
||||
|
||||
def status(_, _) do
|
||||
%Hunter.Status{}
|
||||
end
|
||||
|
||||
def destroy_status(_, _) do
|
||||
true
|
||||
end
|
||||
|
||||
def reblog(_, _) do
|
||||
%Hunter.Status{}
|
||||
end
|
||||
|
||||
def unreblog(_, _) do
|
||||
%Hunter.Status{}
|
||||
end
|
||||
|
||||
def favourite(_, _) do
|
||||
%Hunter.Status{}
|
||||
end
|
||||
|
||||
def unfavourite(_, _) do
|
||||
%Hunter.Status{}
|
||||
end
|
||||
|
||||
def statuses(_, _, _) do
|
||||
[%Hunter.Status{}]
|
||||
end
|
||||
|
||||
def home_timeline(_, _) do
|
||||
[%Hunter.Status{}]
|
||||
end
|
||||
|
||||
def public_timeline(_, _) do
|
||||
|
||||
end
|
||||
|
||||
def hashtag_timeline(_, _, _) do
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
ExUnit.start()
|
Loading…
Reference in New Issue