diff --git a/README.md b/README.md index f0ff966..74aab4a 100644 --- a/README.md +++ b/README.md @@ -1 +1,115 @@ -IyBtcG0tdXJsLXNob3J0ZW5lcgoKQ1JVRCBtYW5hZ2VyIGZvciBtcG0udG8gc2hvcnQgVVJMcyB2aWEgdGhlIFlPVVJMUyAxLjEwLjIgQVBJIGFuZCBhZG1pbiBzZXNzaW9uIGZhbGxiYWNrLgoKKipWZXJzaW9uOioqIDEuMC4wICAKKipBdXRob3I6KiogTVBNIC8gSmFzb24gIAoqKlJlcG86KiogaHR0cHM6Ly9naXQuYWx3aXNwLmNvbS9qYXNvbi9tcG0tdXJsLXNob3J0ZW5lciAgCioqQ29Xb3JrIFByb2plY3Q6KiogQ1ctMDEzIOKAlCBNUE0gVVJMIFNob3J0ZW5lcgoKLS0tCgojIyBPdmVydmlldwoKVGhpcyBza2lsbCBnaXZlcyBDbGF1ZGUgZnVsbCBjcmVhdGUsIHJlYWQsIHVwZGF0ZSwgYW5kIGRlbGV0ZSBjb250cm9sIG92ZXIgc2hvcnQgVVJMcyBvbiBgbXBtLnRvYCwgd2hpY2ggcnVucyBZT1VSTFMgMS4xMC4yLiBDcmVhdGUgYW5kIHJlYWQgYWx3YXlzIHVzZSB0aGUgc3RhdGljIHNpZ25hdHVyZSB0b2tlbiB2aWEgYHlvdXJscy1hcGkucGhwYC4gVXBkYXRlIGFuZCBkZWxldGUgZmlyc3QgYXR0ZW1wdCB0aGUgc2lnbmF0dXJlIHRva2VuIHBhdGggKHdoaWNoIHJlcXVpcmVzIHRoZSBvcHRpb25hbCBgbXBtLWFwaS1leHRyYXNgIFBIUCBwbHVnaW4gdG8gYmUgYWN0aXZlIG9uIHRoZSBzZXJ2ZXIpOyBpZiB0aGUgcGx1Z2luIGlzIG5vdCBpbnN0YWxsZWQsIHRoZXkgYXV0b21hdGljYWxseSBmYWxsIGJhY2sgdG8gYW4gYWRtaW4gYnJvd3NlciBzZXNzaW9uIGF1dGhlbnRpY2F0ZWQgdmlhIGBhZG1pbi9gIHdpdGggYSB0aW1lLWxpbWl0ZWQgbG9naW4gbm9uY2UuIEFsbCBjcmVkZW50aWFscyBhcmUgc3RvcmVkIGluIG1hY09TIEtleWNoYWluIHVuZGVyIHRoZSBzZXJ2aWNlIG5hbWUgYG1wbS50by15b3VybHNgLiBUaGUgc2tpbGwgYWxzbyBpbmNsdWRlcyB0aGUgY29tcGFuaW9uIFBIUCBwbHVnaW4gKGBtcG0tYXBpLWV4dHJhcy5waHBgKSB0aGF0IGV4dGVuZHMgdGhlIFlPVVJMUyBBUEkgdG8gc3VwcG9ydCB1cGRhdGUgYW5kIGRlbGV0ZSBhY3Rpb25zIG5hdGl2ZWx5LCBlbGltaW5hdGluZyB0aGUgbmVlZCBmb3IgdGhlIHNlc3Npb24gZmFsbGJhY2suCgotLS0KCiMjIFNraWxscwoKfCBTa2lsbCB8IFdoYXQgSXQgRG9lcyB8CnwtLS18LS0tfAp8IGBtcG0tdXJsLXNob3J0ZW5lcmAgfCBNYW5hZ2VzIHNob3J0IFVSTHMgb24gbXBtLnRvLiBUcmlnZ2VycyBvbjogInNob3J0ZW4gdGhpcyBVUkwiLCAiY3JlYXRlIGEgc2hvcnQgbGluayIsICJtYWtlIGEgc2hvcnQgVVJMIiwgIm1wbS50byIsICJzaG9ydCBsaW5rIGZvciIsICJzaG9ydCBVUkwgZm9yIiwgImRlbGV0ZSB0aGlzIHNob3J0IGxpbmsiLCAidXBkYXRlIHRoZSBzaG9ydCBVUkwgZm9yIiwgIndoYXQgZG9lcyBtcG0udG8vWFhYIHBvaW50IHRvIiwgImxpc3Qgb3VyIHNob3J0IFVSTHMiLCAiY2hhbmdlIHRoZSBzaG9ydCBjb2RlIiwgInJlbmFtZSB0aGUga2V5d29yZCIuIFN1cHBvcnRzIGFsbCBDUlVEIG9wZXJhdGlvbnM6IGNyZWF0ZSAod2l0aCBvcHRpb25hbCBrZXl3b3JkIGFuZCB0aXRsZSksIHJlYWQgKGV4cGFuZCArIGNsaWNrIHN0YXRzKSwgbGlzdCAodG9wL2JvdHRvbS9sYXN0L3JhbmRvbSksIHVwZGF0ZSAoVVJMLCBrZXl3b3JkLCBhbmQvb3IgdGl0bGUpLCBhbmQgZGVsZXRlICh3aXRoIGNvbmZpcm1hdGlvbiBwcm9tcHQpLiB8CgotLS0KCiMjIFRvb2xzIFJlZmVyZW5jZQoKfCBNb2R1bGUgfCBUb29scyB8CnwtLS18LS0tfAp8ICoqWU9VUkxTIEFQSSoqIHwgYHlvdXJscy1hcGkucGhwYCDigJQgYHNob3J0dXJsYCAoY3JlYXRlKSwgYGV4cGFuZGAgKHJlYWQpLCBgdXJsLXN0YXRzYCAocmVhZCBzdGF0cyksIGBzdGF0c2AgKGxpc3QpLCBgZGItc3RhdHNgIChjb25uZWN0aW9uIGNoZWNrKSB8CnwgKipZT1VSTFMgQWRtaW4gQWpheCoqIHwgYGFkbWluL2FkbWluLWFqYXgucGhwYCDigJQgYGRlbGV0ZWAgKGFkbWluIGZhbGxiYWNrKSwgYGVkaXRfZGlzcGxheWAgKGFkbWluIGZhbGxiYWNrKSwgYGVkaXRfc2F2ZWAgKGFkbWluIGZhbGxiYWNrKSB8CnwgKiptcG0tYXBpLWV4dHJhcyBwbHVnaW4qKiB8IEFkZHMgYHVwZGF0ZWAgYW5kIGBkZWxldGVgIGFjdGlvbnMgdG8gYHlvdXJscy1hcGkucGhwYCwgZW5hYmxpbmcgc2lnbmF0dXJlLXRva2VuLW9ubHkgb3BlcmF0aW9uIHdpdGhvdXQgYWRtaW4gY3JlZGVudGlhbHMgfAp8ICoqbWFjT1MgS2V5Y2hhaW4qKiB8IGBzZWN1cml0eSBmaW5kLWdlbmVyaWMtcGFzc3dvcmRgLCBgc2VjdXJpdHkgYWRkLWdlbmVyaWMtcGFzc3dvcmRgLCBgc2VjdXJpdHkgZGVsZXRlLWdlbmVyaWMtcGFzc3dvcmRgIOKAlCBzdG9yZXMgYHNpZ25hdHVyZWAsIGB1c2VybmFtZWAsIGBwYXNzd29yZGAgfAoKLS0tCgojIyBTZXR1cCBJbnN0cnVjdGlvbnMKCioqU3RlcC1ieS1zdGVwOioqCgoxLiBJbnN0YWxsIFB5dGhvbiBkZXBlbmRlbmN5OiBgcGlwMyBpbnN0YWxsIHJlcXVlc3RzIC0tYnJlYWstc3lzdGVtLXBhY2thZ2VzYAoyLiBSdW4gc2V0dXAgdG8gc3RvcmUgY3JlZGVudGlhbHM6IGBweXRob24zIHNjcmlwdHMveW91cmxzX21hbmFnZXIucHkgc2V0dXBgCiAgIC0gKipTaWduYXR1cmUgdG9rZW4qKiAocmVxdWlyZWQpOiBmb3VuZCBpbiBZT1VSTFMgYWRtaW4g4oaSIFRvb2xzIOKGkiBTZWN1cmUgVG9rZW4KICAgLSAqKkFkbWluIHVzZXJuYW1lICsgcGFzc3dvcmQqKiAob3B0aW9uYWwpOiB1c2VkIGFzIGZhbGxiYWNrIHdoZW4gdGhlIG1wbS1hcGktZXh0cmFzIHBsdWdpbiBpcyBub3QgYWN0aXZlCjMuIFZlcmlmeSB0aGUgY29ubmVjdGlvbjogYHB5dGhvbjMgc2NyaXB0cy95b3VybHNfbWFuYWdlci5weSBjaGVja2AKNC4gKE9wdGlvbmFsKSBJbnN0YWxsIHRoZSBQSFAgcGx1Z2luIG9uIHRoZSBZT1VSTFMgc2VydmVyIHRvIGVuYWJsZSBBUEktYmFzZWQgdXBkYXRlIGFuZCBkZWxldGU6CiAgIC0gQ29weSBgcGx1Z2luL21wbS1hcGktZXh0cmFzLnBocGAgdG8gdGhlIFlPVVJMUyBzZXJ2ZXIgYXQgYHVzZXIvcGx1Z2lucy9tcG0tYXBpLWV4dHJhcy9tcG0tYXBpLWV4dHJhcy5waHBgCiAgIC0gTG9nIGluIHRvIFlPVVJMUyBhZG1pbiDihpIgTWFuYWdlIFBsdWdpbnMg4oaSIGFjdGl2YXRlICoqTVBNIEFQSSBFeHRyYXMqKgogICAtIFJlLXJ1biBgY2hlY2tgIOKAlCB0aGUgcGx1Z2luIHN0YXR1cyBsaW5lIHNob3VsZCBzaG93IOKckyBhY3RpdmUKNS4gVG8gYWRkIHRoZSBTS0lMTC5tZCB0byBDb3dvcms6IGluc3RhbGwgdGhlIGAuc2tpbGxgIGZpbGUgdmlhIHRoZSBDb3dvcmsgcGx1Z2luIG1hbmFnZXIKCiMjIyBTZXR1cCBDaGVja2xpc3QKCi0gWyBdIFB5dGhvbiAzLjkrIGF2YWlsYWJsZSAoYHB5dGhvbjMgLS12ZXJzaW9uYCkKLSBbIF0gYHJlcXVlc3RzYCBsaWJyYXJ5IGluc3RhbGxlZCAoYHBpcDMgaW5zdGFsbCByZXF1ZXN0cyAtLWJyZWFrLXN5c3RlbS1wYWNrYWdlc2ApCi0gWyBdIFNpZ25hdHVyZSB0b2tlbiBzdG9yZWQgdmlhIGBzZXR1cGAgY29tbWFuZAotIFsgXSBgY2hlY2tgIGNvbW1hbmQgc3VjY2VlZHMg4oCUIHNob3dzIGxpbmsgY291bnQgYW5kIGNsaWNrIHRvdGFsCi0gWyBdIChPcHRpb25hbCkgbXBtLWFwaS1leHRyYXMgcGx1Z2luIGluc3RhbGxlZCBhbmQgYWN0aXZlIG9uIHNlcnZlcgotIFsgXSAoT3B0aW9uYWwpIEFkbWluIGNyZWRlbnRpYWxzIHN0b3JlZCBmb3Igc2Vzc2lvbiBmYWxsYmFjawoKLS0tCgojIyBDb25uZWN0aW9uIERldGFpbHMKCnwgRmllbGQgfCBWYWx1ZSB8CnwtLS18LS0tfAp8IEluc3RhbmNlIHwgaHR0cHM6Ly9tcG0udG8gfAp8IEFQSSBlbmRwb2ludCB8IGh0dHBzOi8vbXBtLnRvL3lvdXJscy1hcGkucGhwIHwKfCBBZG1pbiBVUkwgfCBodHRwczovL21wbS50by9hZG1pbi8gfAp8IEF1dGggbWV0aG9kIChjcmVhdGUvcmVhZCkgfCBTdGF0aWMgc2lnbmF0dXJlIHRva2VuIHZpYSBgP3NpZ25hdHVyZT1gIFBPU1QgcGFyYW0gfAp8IEF1dGggbWV0aG9kICh1cGRhdGUvZGVsZXRlLCBwbHVnaW4pIHwgU2lnbmF0dXJlIHRva2VuICsgYG1wbS1hcGktZXh0cmFzYCBwbHVnaW4gfAp8IEF1dGggbWV0aG9kICh1cGRhdGUvZGVsZXRlLCBmYWxsYmFjaykgfCBVc2VybmFtZSArIHBhc3N3b3JkIHNlc3Npb24gY29va2llIHZpYSBhZG1pbi8gbm9uY2UgbG9naW4gfAp8IEtleWNoYWluIHNlcnZpY2UgfCBgbXBtLnRvLXlvdXJsc2AgfAp8IEtleWNoYWluIGFjY291bnRzIHwgYHNpZ25hdHVyZWAsIGB1c2VybmFtZWAsIGBwYXNzd29yZGAgfAp8IFlPVVJMUyB2ZXJzaW9uIHwgMS4xMC4yIHwKCi0tLQoKIyMgV29ya2Zsb3cgTm90ZXMKCioqS2V5d29yZCBjaGFyc2V0OioqIGBtcG0udG9gIGlzIGNvbmZpZ3VyZWQgd2l0aCBhIGxvd2VyY2FzZSBhbHBoYW51bWVyaWMgY2hhcnNldCBvbmx5LiBVcHBlcmNhc2UgbGV0dGVycywgaHlwaGVucywgdW5kZXJzY29yZXMsIGFuZCBhbGwgb3RoZXIgc3BlY2lhbCBjaGFyYWN0ZXJzIGFyZSBzaWxlbnRseSBzdHJpcHBlZCBieSBZT1VSTFMuIFRoZSBzY3JpcHQgbm9ybWFsaXNlcyBrZXl3b3JkcyBjbGllbnQtc2lkZSBiZWZvcmUgc2VuZGluZyAoYHJlLnN1YihyJ1teYS16MC05XScsICcnLCByYXcubG93ZXIoKSlgKSBhbmQgd2FybnMgdGhlIHVzZXIgaWYgbm9ybWFsaXNhdGlvbiBjaGFuZ2VkIHRoZWlyIHJlcXVlc3RlZCBrZXl3b3JkLgoKKipBZG1pbiBsb2dpbiBmbG93OioqIFlPVVJMUyAxLjEwLjIgZG9lcyBub3QgaGF2ZSBhIHN0YW5kYWxvbmUgYGxvZ2luLnBocGAuIFRoZSBsb2dpbiBmb3JtIGlzIHNlcnZlZCBieSBgYWRtaW4vYCAoaW5kZXgucGhwKSwgd2hpY2ggZW1iZWRzIGEgdGltZS1saW1pdGVkIGA8aW5wdXQgbmFtZT0ibm9uY2UiPmAgb24gdGhlIHBhZ2UuIFRoZSBzY3JpcHQgR0VUcyBgYWRtaW4vYCB0byBleHRyYWN0IHRoaXMgbm9uY2UsIHRoZW4gUE9TVHMgdG8gYGFkbWluL2Agd2l0aCBge3VzZXJuYW1lLCBwYXNzd29yZCwgbm9uY2UsIHN1Ym1pdH1gLiBTdWNjZXNzZnVsIGxvZ2luIGlzIGNvbmZpcm1lZCBieSB0aGUgYWJzZW5jZSBvZiBgbmFtZT0icGFzc3dvcmQiYCBpbiB0aGUgcmVzcG9uc2UgYm9keS4KCioqQWRtaW4gcGFnZSBzZWFyY2g6KiogV2l0aCA2NzErIGxpbmtzIGluIHRoZSBkYXRhYmFzZSwgdGhlIHRhcmdldCBrZXl3b3JkIHdvdWxkIG5vdCBhcHBlYXIgb24gcGFnZSAxIG9mIHRoZSBhZG1pbiB0YWJsZS4gVGhlIHNjcmlwdCBzZWFyY2hlcyB0aGUgYWRtaW4gcGFnZSB1c2luZyBgP3M9S0VZV09SRCZzZWFyY2hfaW49a2V5d29yZGAgc28gWU9VUkxTIGZpbHRlcnMgdGhlIHRhYmxlIHRvIGEgc2luZ2xlIG1hdGNoaW5nIHJvdyBiZWZvcmUgc2NyYXBpbmcgbm9uY2UgbGlua3MgZnJvbSBgYWRtaW4tYWpheC5waHBgIGhyZWZzLgoKKipQbHVnaW4gZGV0ZWN0aW9uOioqIE9uIGV2ZXJ5IHVwZGF0ZS9kZWxldGUgYXR0ZW1wdCwgdGhlIHNjcmlwdCBwcm9iZXMgZm9yIHRoZSBgbXBtLWFwaS1leHRyYXNgIHBsdWdpbiBieSBjaGVja2luZyB3aGV0aGVyIFlPVVJMUyByZXR1cm5zIGBlcnJvckNvZGU6IDQwMGAgd2l0aCAidW5rbm93biIvIm1pc3NpbmciLyJhY3Rpb24iIGluIHRoZSBtZXNzYWdlIGJvZHkuIElmIGl0IGRvZXMsIHRoZSBzY3JpcHQgZmFsbHMgYmFjayB0byB0aGUgYWRtaW4gc2Vzc2lvbiBwYXRoIGF1dG9tYXRpY2FsbHkuCgoqKm1wbS50byByb290IHJlZGlyZWN0OioqIGBtcG0udG8vYCAzMDItcmVkaXJlY3RzIHRvIGB3d3cubXBtZWRpYS50dmAgKFdvcmRQcmVzcykuIEFkbWluIHNlc3Npb24gY29va2llcyBhcmUgc2NvcGVkIHRvIGAubXBtLnRvYC4gRG8gbm90IGZvbGxvdyByZWRpcmVjdHMgd2hlbiBmZXRjaGluZyBgYWRtaW4vYCBmb3IgdGhlIGluaXRpYWwgbG9naW4gbm9uY2UgR0VULgoKLS0tCgojIyBSZXF1aXJlbWVudHMKCi0gUHl0aG9uIDMuOSsKLSBgcmVxdWVzdHNgIGxpYnJhcnkgKGBwaXAzIGluc3RhbGwgcmVxdWVzdHMgLS1icmVhay1zeXN0ZW0tcGFja2FnZXNgKQotIG1hY09TIChmb3IgS2V5Y2hhaW4gdmlhIGBzZWN1cml0eWAgQ0xJKQotIE5ldHdvcmsgYWNjZXNzIHRvIGBtcG0udG9gCi0gWU9VUkxTIHNpZ25hdHVyZSB0b2tlbiAocmVxdWlyZWQpCi0gWU9VUkxTIGFkbWluIHVzZXJuYW1lICsgcGFzc3dvcmQgKG9wdGlvbmFsLCBmb3IgdXBkYXRlL2RlbGV0ZSBmYWxsYmFjayB3aXRob3V0IHBsdWdpbikKCi0tLQoKIyMgVHJvdWJsZXNob290aW5nCgp8IFN5bXB0b20gfCBGaXggfAp8LS0tfC0tLXwKfCBgRXJyb3I6IE5vIHNpZ25hdHVyZSB0b2tlbiBmb3VuZGAgfCBSdW4gYHlvdXJsc19tYW5hZ2VyLnB5IHNldHVwYCBhbmQgZW50ZXIgeW91ciBzaWduYXR1cmUgdG9rZW4gfAp8IGBFcnJvcjogQWRtaW4gbG9naW4gZmFpbGVkYCB8IFJlLXJ1biBgc2V0dXBgIGFuZCByZS1lbnRlciBhZG1pbiB1c2VybmFtZSArIHBhc3N3b3JkOyB2ZXJpZnkgYXQgbXBtLnRvL2FkbWluLyB8CnwgYEVycm9yOiBDb3VsZCBub3QgZmluZCBsb2dpbiBub25jZSBvbiBhZG1pbiBwYWdlYCB8IFlPVVJMUyBhZG1pbiBwYWdlIHN0cnVjdHVyZSBjaGFuZ2VkIOKAlCBjaGVjayBgbXBtLnRvL2FkbWluL2AgbWFudWFsbHk7IHVwZGF0ZSByZWdleCBpZiBuZWVkZWQgfAp8IGBFcnJvcjogU2hvcnQgY29kZSAnWCcgbm90IGZvdW5kIG9uIGFkbWluIHBhZ2VgIHwgS2V5d29yZCBkb2Vzbid0IGV4aXN0IG9yIHdhcyBkZWxldGVkOyBjaGVjayB3aXRoIGByZWFkIC0ta2V5d29yZCBYYCBmaXJzdCB8CnwgYHJlcXVlc3RzYCBub3QgZm91bmQgfCBSdW4gYHBpcDMgaW5zdGFsbCByZXF1ZXN0cyAtLWJyZWFrLXN5c3RlbS1wYWNrYWdlc2AgfAp8IFVwZGF0ZS9kZWxldGUgdmlhIEFQSSByZXR1cm5zICJ1bmtub3duIGFjdGlvbiIgfCBtcG0tYXBpLWV4dHJhcyBwbHVnaW4gaXMgbm90IGFjdGl2ZTsgZWl0aGVyIGluc3RhbGwgaXQgb3IgZW5zdXJlIGFkbWluIGNyZWRlbnRpYWxzIGFyZSBzdG9yZWQgZm9yIHNlc3Npb24gZmFsbGJhY2sgfAp8IEFkbWluIGNvb2tpZXMgbm90IHBlcnNpc3RpbmcgfCBgbXBtLnRvL2Agcm9vdCByZWRpcmVjdHMgdG8gV29yZFByZXNzOyBkbyBub3QgZm9sbG93IHJlZGlyZWN0cyBvbiB0aGUgaW5pdGlhbCBub25jZSBHRVQgKGBhbGxvd19yZWRpcmVjdHM9RmFsc2VgKSB8CnwgYEVycm9yOiBDb3VsZCBub3QgZXh0cmFjdCBlZGl0LXNhdmUgbm9uY2VgIHwgQWRtaW4gcGFnZSBzdHJ1Y3R1cmUgY2hhbmdlZCBmb3IgdGhlIGVkaXQgZm9ybTsgYWN0aXZhdGUgdGhlIHBsdWdpbiBpbnN0ZWFkIGFzIGEgd29ya2Fyb3VuZCB8Cg== \ No newline at end of file +# mpm-url-shortener + +CRUD manager for mpm.to short URLs via the YOURLS 1.10.2 API and admin session fallback. + +**Version:** 1.0.0 +**Author:** MPM / Jason +**Repo:** https://git.alwisp.com/jason/mpm-url-shortener +**CoWork Project:** CW-013 — MPM URL Shortener + +--- + +## Overview + +This skill gives Claude full create, read, update, and delete control over short URLs on `mpm.to`, which runs YOURLS 1.10.2. Create and read always use the static signature token via `yourls-api.php`. Update and delete first attempt the signature token path (which requires the optional `mpm-api-extras` PHP plugin to be active on the server); if the plugin is not installed, they automatically fall back to an admin browser session authenticated via `admin/` with a time-limited login nonce. All credentials are stored in macOS Keychain under the service name `mpm.to-yourls`. The skill also includes the companion PHP plugin (`mpm-api-extras.php`) that extends the YOURLS API to support update and delete actions natively, eliminating the need for the session fallback. + +--- + +## Skills + +| Skill | What It Does | +|---|---| +| `mpm-url-shortener` | Manages short URLs on mpm.to. Triggers on: "shorten this URL", "create a short link", "make a short URL", "mpm.to", "short link for", "short URL for", "delete this short link", "update the short URL for", "what does mpm.to/XXX point to", "list our short URLs", "change the short code", "rename the keyword". Supports all CRUD operations: create (with optional keyword and title), read (expand + click stats), list (top/bottom/last/random), update (URL, keyword, and/or title), and delete (with confirmation prompt). | + +--- + +## Tools Reference + +| Module | Tools | +|---|---| +| **YOURLS API** | `yourls-api.php` — `shorturl` (create), `expand` (read), `url-stats` (read stats), `stats` (list), `db-stats` (connection check) | +| **YOURLS Admin Ajax** | `admin/admin-ajax.php` — `delete` (admin fallback), `edit_display` (admin fallback), `edit_save` (admin fallback) | +| **mpm-api-extras plugin** | Adds `update` and `delete` actions to `yourls-api.php`, enabling signature-token-only operation without admin credentials | +| **macOS Keychain** | `security find-generic-password`, `security add-generic-password`, `security delete-generic-password` — stores `signature`, `username`, `password` | + +--- + +## Setup Instructions + +**Step-by-step:** + +1. Install Python dependency: `pip3 install requests --break-system-packages` +2. Run setup to store credentials: `python3 scripts/yourls_manager.py setup` + - **Signature token** (required): found in YOURLS admin → Tools → Secure Token + - **Admin username + password** (optional): used as fallback when the mpm-api-extras plugin is not active +3. Verify the connection: `python3 scripts/yourls_manager.py check` +4. (Optional) Install the PHP plugin on the YOURLS server to enable API-based update and delete: + - Copy `plugin/mpm-api-extras.php` to the YOURLS server at `user/plugins/mpm-api-extras/mpm-api-extras.php` + - Log in to YOURLS admin → Manage Plugins → activate **MPM API Extras** + - Re-run `check` — the plugin status line should show ✓ active +5. To add the SKILL.md to Cowork: install the `.skill` file via the Cowork plugin manager + +### Setup Checklist + +- [ ] Python 3.9+ available (`python3 --version`) +- [ ] `requests` library installed (`pip3 install requests --break-system-packages`) +- [ ] Signature token stored via `setup` command +- [ ] `check` command succeeds — shows link count and click total +- [ ] (Optional) mpm-api-extras plugin installed and active on server +- [ ] (Optional) Admin credentials stored for session fallback + +--- + +## Connection Details + +| Field | Value | +|---|---| +| Instance | https://mpm.to | +| API endpoint | https://mpm.to/yourls-api.php | +| Admin URL | https://mpm.to/admin/ | +| Auth method (create/read) | Static signature token via `?signature=` POST param | +| Auth method (update/delete, plugin) | Signature token + `mpm-api-extras` plugin | +| Auth method (update/delete, fallback) | Username + password session cookie via admin/ nonce login | +| Keychain service | `mpm.to-yourls` | +| Keychain accounts | `signature`, `username`, `password` | +| YOURLS version | 1.10.2 | + +--- + +## Workflow Notes + +**Keyword charset:** `mpm.to` is configured with a lowercase alphanumeric charset only. Uppercase letters, hyphens, underscores, and all other special characters are silently stripped by YOURLS. The script normalises keywords client-side before sending (`re.sub(r'[^a-z0-9]', '', raw.lower())`) and warns the user if normalisation changed their requested keyword. + +**Admin login flow:** YOURLS 1.10.2 does not have a standalone `login.php`. The login form is served by `admin/` (index.php), which embeds a time-limited `` on the page. The script GETs `admin/` to extract this nonce, then POSTs to `admin/` with `{username, password, nonce, submit}`. Successful login is confirmed by the absence of `name="password"` in the response body. + +**Admin page search:** With 671+ links in the database, the target keyword would not appear on page 1 of the admin table. The script searches the admin page using `?s=KEYWORD&search_in=keyword` so YOURLS filters the table to a single matching row before scraping nonce links from `admin-ajax.php` hrefs. + +**Plugin detection:** On every update/delete attempt, the script probes for the `mpm-api-extras` plugin by checking whether YOURLS returns `errorCode: 400` with "unknown"/"missing"/"action" in the message body. If it does, the script falls back to the admin session path automatically. + +**mpm.to root redirect:** `mpm.to/` 302-redirects to `www.mpmedia.tv` (WordPress). Admin session cookies are scoped to `.mpm.to`. Do not follow redirects when fetching `admin/` for the initial login nonce GET. + +--- + +## Requirements + +- Python 3.9+ +- `requests` library (`pip3 install requests --break-system-packages`) +- macOS (for Keychain via `security` CLI) +- Network access to `mpm.to` +- YOURLS signature token (required) +- YOURLS admin username + password (optional, for update/delete fallback without plugin) + +--- + +## Troubleshooting + +| Symptom | Fix | +|---|---| +| `Error: No signature token found` | Run `yourls_manager.py setup` and enter your signature token | +| `Error: Admin login failed` | Re-run `setup` and re-enter admin username + password; verify at mpm.to/admin/ | +| `Error: Could not find login nonce on admin page` | YOURLS admin page structure changed — check `mpm.to/admin/` manually; update regex if needed | +| `Error: Short code 'X' not found on admin page` | Keyword doesn't exist or was deleted; check with `read --keyword X` first | +| `requests` not found | Run `pip3 install requests --break-system-packages` | +| Update/delete via API returns "unknown action" | mpm-api-extras plugin is not active; either install it or ensure admin credentials are stored for session fallback | +| Admin cookies not persisting | `mpm.to/` root redirects to WordPress; do not follow redirects on the initial nonce GET (`allow_redirects=False`) | +| `Error: Could not extract edit-save nonce` | Admin page structure changed for the edit form; activate the plugin instead as a workaround |