{"id":27962612,"url":"https://github.com/mirtyl-wacdec/urbit_ex","last_synced_at":"2025-05-07T19:56:41.185Z","repository":{"id":57556527,"uuid":"342649026","full_name":"mirtyl-wacdec/urbit_ex","owner":"mirtyl-wacdec","description":"Elixir library enablign full interaction with Urbit servers","archived":false,"fork":false,"pushed_at":"2021-11-05T09:51:23.000Z","size":57,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-07T19:56:35.665Z","etag":null,"topics":["elixir","urbit"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mirtyl-wacdec.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-26T17:24:32.000Z","updated_at":"2024-05-07T05:59:16.000Z","dependencies_parsed_at":"2022-09-06T06:13:00.397Z","dependency_job_id":null,"html_url":"https://github.com/mirtyl-wacdec/urbit_ex","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirtyl-wacdec%2Furbit_ex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirtyl-wacdec%2Furbit_ex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirtyl-wacdec%2Furbit_ex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirtyl-wacdec%2Furbit_ex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mirtyl-wacdec","download_url":"https://codeload.github.com/mirtyl-wacdec/urbit_ex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252949317,"owners_count":21830150,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elixir","urbit"],"created_at":"2025-05-07T19:56:40.653Z","updated_at":"2025-05-07T19:56:41.173Z","avatar_url":"https://github.com/mirtyl-wacdec.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# UrbitEx\n\nUrbitEx is an Elixir package which allows you to connect to a running Urbit instance.\nIt is a batteries-included, opinionated library, with functionality baked in to build an Urbit client right away, with little need to add additional logic.\nBut it also exposes low-level APIs if you feel like rolling your own logic on raw Urbit primaries, e.g. poke, scry, raw SSE event handling, etc.\n\n## Installation\nThe package is published at Hex, please look at https://hex.pm/packages/urbit_ex.\n\nThe package can be installed by adding `urbit_ex` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:urbit_ex, \"~\u003e 0.7.2\"}\n  ]\nend\n```\n\nOr clone this repo and point `mix.exs` to its location:\n```elixir\ndef deps do\n  [\n    {:urbit_ex, path: \"path/to/folder\"}\n  ]\nend\n```\n\n## Use\nBig changes since last version!\nAfter adding it to your dependencies, connect to an Urbit ship by running: \n```elixir\n{:ok, pid} = UrbitEx.start_link(url, code, name \\\\ :urbit)\n```\nOr \n```elixir \n{:ok, pid} = UrbitEx.start(url, code, name \\\\ :urbit)\n``` \nif you want an unlinked process. e.g. \n```elixir\n{:ok, pid} = UrbitEx.start_link(\"http://localhost\", \"sampel-sampel-sampel-sampel\")\n```\nThis will login to your Urbit ship and start a GenServer with the passed name atom keeping the state for your Urbit session. and start the EventSource pipeline. You can fetch your Urbit session's state any time with \n```elixir\nUrbitEx.get(name \\\\ :urbit)\n```\n\nYou will need to subscribe to gall apps in order to your Urbit ship to start sending any events to Elixir. You can do so by adding an eyre channel. As most things in these API, there's two ways of doing that.\n1. The easy way:\n```elixir\nUrbitEx.new_channel(name \\\\ :main)\n```\n\nThis will open a new channel (by default called `:main`) and subscribe to all the apps that Landscape subscribes to. It will also activate the default reducer, which automatically processes Urbit events and keeps state of your session in the `UrbitEx.Session` GenServer.\n\n2. The hard way:\n```elixir \nUrbitEx.Session.add_channel(name: main, parent: :urbit, keep_state: true)\n```\nThis will open an eyre channel and a Channel GenServer to keep its state. You then must manually subscribe to gall apps in order to receive events. You do so by passing a list of subscriptions to \n```elixir \nUrbitEx.API.subscribe(session, channel, list)\n```\ne.g.\n```elixir\nsession = UrbitEx.get()\nchannel = UrbitEx.Channel.read(:main)\nlist = [\n        %{app: \"metadata-store\", path: \"/all\"},\n        %{app: \"group-view\", path: \"/all\"},\n        %{app: \"group-store\", path: \"/groups\"},\n        %{app: \"graph-store\", path: \"/keys\"},\n        %{app: \"graph-store\", path: \"/updates\"},\n        %{app: \"invite-store\", path: \"/all\"},\n        %{app: \"launch\", path: \"/all\"},\n        %{app: \"weather\", path: \"/all\"},\n        %{app: \"contact-store\", path: \"/all\"},\n        %{app: \"hark-store\", path: \"/updates\"},\n        %{app: \"hark-graph-hook\", path: \"/updates\"},\n        %{app: \"hark-group-hook\", path: \"/updates\"},\n        %{app: \"settings-store\", path: \"/all\"},\n        %{app: \"s3-store\", path: \"/all\"},\n        %{app: \"contact-pull-hook\", path: \"/nacks\"},\n        %{app: \"dm-hook\", path: \"/updates\"}\n      ]\nUrbitEx.API.subscribe(session, channel, list)\n```\nYou can add multiple channels with separate or overlapping subscriptions.\n\nSubscription will trigger your Urbit ship to start sending Server Side Events (SSE, aka EventSource, EventStream). \nUrbitEx has a built-in reducer (see `reducer.ex` in the repo) to parse and process the raw events sent by your Urbit ship. \nThe built-in reducer does two things: \n1. If the channel was started with the `keep_state` flag given as `true`, the Session struct will keep the basic state of your session: pending notifications, unreads, pending group joins, pending invites, channel metadata, contacts; i.e. all the state that Landscape keeps and any Urbit client would need to function.\n2. The reducer parses urbit events and then broadcasts them to any consumers of the Channel GenServer. You can subscribe to these events with:\n```elixir\nUrbitEx.Channel.consume_feed(channel, consumer_pid)\n```\ne.g.\n```elixir\nUrbitEx.Channel.consume_feed(:main, self())\n```\nYou can then handle those events as you wish. To see the format of the events sent, check the `channel.ex` and `reducer.ex` files in the repo.\n\nIf you would prefer to parse Urbit events on your own and not use the default reducer, you can subscribe to the raw eyre SSE events by using:\n```elixir\nUrbitEx.Channel.consume_raw(channel, consumer_pid)\n```\nYou can stop the subscriptions by using:\n```elixir\nUrbitEx.Channel.wean(channel, consumer_pid)\nUrbitEx.Channel.wean_raw(channel, consumer_pid)\n```\nrespectively. Ad-hoc consumption and weaning is very convenient if you want to handle an event inside `Task.async`, for example.\n\nFor version 0.6.0 full functionality (at least Landscape-equivalent) for all Gall Apps has been implemented. \n\nYou can easily create, join, leave, delete groups and channels, post messages and edit them, all Landscape functionality and then some (e.g. ban comets from your group!).\neg.\n\n```elixir\nr = UrbitEx.Resource.new(\"dopzod\", \"urbit-help\")\nmessage = \"My Elixir API is too awesome, please help\")\nUrbitEx.API.Graph.send_message(session, r, message)\n```\n\nPlease look at all files inside the `api/` folder for individual module docs. There's even support for virtual terminal! Check out `api/gall/herm.ex` for detail.\n\nStructs added as soft type specs for most data structures, e.g. `Resource`, `Graph`, `Post`, `Node`, Notifications, etc. Tildes are generally added or removed automatically as necessary to interact with Eyre.\n\nThis library also includes an implementation of Herb, a way to evaluate `dojo` code from the outside. You can call it passing the loopbackport and some dojo command.\n\n```elixir\nUrbitEx.herb(12321, \"+trouble\")\n```\n\nFor more documentation (much improved), look inside the repo or at https://hexdocs.pm/urbit_ex/0.6.5/UrbitEx.API.html#content.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmirtyl-wacdec%2Furbit_ex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmirtyl-wacdec%2Furbit_ex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmirtyl-wacdec%2Furbit_ex/lists"}